[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/nl.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Zoekcontext voor producten",
  "admin/editor.product-search.maxItemsPerPage": "Maximum aantal items per pagina",
  "admin/editor.product-search.hideUnavailableItems": "Verberg niet-beschikbare items",
  "store/store.network-status.offline": "Geen internetverbinding.",
  "admin/actions.enable-binding": "Configuratie inschakelen door binding",
  "admin/actions.binding-configurations": "Bindende configuraties",
  "admin/actions.binding-id": "Bindende ID",
  "admin/actions.binding-description": "Voer de bindende ID in"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/de.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Kontext der Produktsuche",
  "admin/editor.product-search.maxItemsPerPage": "Maximale Anzahl von Artikeln pro Seite",
  "admin/editor.product-search.hideUnavailableItems": "Nicht verfügbare Artikel ausblenden",
  "store/store.network-status.offline": "Keine Internetverbindung.",
  "admin/actions.enable-binding": "Konfiguration durch Bindung aktivieren",
  "admin/actions.binding-configurations": "Bindung-Konfigurationen",
  "admin/actions.binding-id": "Bindungs-ID",
  "admin/actions.binding-description": "Geben Sie die Bindungs-ID ein"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/pl.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Kontekst wyszukiwania produktu",
  "admin/editor.product-search.maxItemsPerPage": "Maksymalna liczba pozycji na stronę",
  "admin/editor.product-search.hideUnavailableItems": "Ukryj niedostępne pozycje",
  "store/store.network-status.offline": "Brak połączenia z Internetem.",
  "admin/actions.enable-binding": "Włącz konfigurację przez powiązanie",
  "admin/actions.binding-configurations": "Konfiguracje powiązań",
  "admin/actions.binding-id": "Identyfikator powiązania",
  "admin/actions.binding-description": "Wpisz identyfikator powiązania"
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/id-ID.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Konteks pencarian produk",
  "admin/editor.product-search.maxItemsPerPage": "Jumlah maksimum item per halaman",
  "admin/editor.product-search.hideUnavailableItems": "Sembunyikan item yang tidak tersedia",
  "store/store.network-status.offline": "Tidak ada koneksi internet.",
  "admin/actions.enable-binding": "Aktifkan konfigurasi dengan pengikatan",
  "admin/actions.binding-configurations": "Konfigurasi pengikatan"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/pt.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Contexto de busca de produtos",
  "admin/editor.product-search.maxItemsPerPage": "Número máximo de elementos por página",
  "admin/editor.product-search.hideUnavailableItems": "Esconder itens indisponíveis",
  "store/store.network-status.offline": "Sem conexão à internet.",
  "admin/actions.enable-binding": "Habilitar configuração por vínculo",
  "admin/actions.binding-configurations": "Configurações de vínculos",
  "admin/actions.binding-id": "ID de vínculo",
  "admin/actions.binding-description": "Insira o ID de vínculo"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/ar-SA.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "سياق البحث عن المنتج",
  "admin/editor.product-search.maxItemsPerPage": "الحد الأقصى لعدد العناصر في كل صفحة",
  "admin/editor.product-search.hideUnavailableItems": "إخفاء العناصر غير المتاحة",
  "store/store.network-status.offline": "لا يوجد اتصال بالإنترنت.",
  "admin/actions.enable-binding": "Enable configuration by binding",
  "admin/actions.binding-configurations": "Binding configurations",
  "admin/actions.binding-id": "Binding ID",
  "admin/actions.binding-description": "Enter the binding ID"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/en.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Product search context",
  "admin/editor.product-search.maxItemsPerPage": "Maximum number of items per page",
  "admin/editor.product-search.hideUnavailableItems": "Hide unavailable items",
  "store/store.network-status.offline": "No internet connection.",
  "admin/actions.enable-binding": "Enable configuration by binding",
  "admin/actions.binding-configurations": "Binding configurations",
  "admin/actions.binding-id": "Binding ID",
  "admin/actions.binding-description": "Enter the binding ID"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/no-NO.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Produktsøk kontekst",
  "admin/editor.product-search.maxItemsPerPage": "Maksimalt antall varer per side",
  "admin/editor.product-search.hideUnavailableItems": "Skjul utilgjengelige varer",
  "store/store.network-status.offline": "Ingen Internett-forbindelse.",
  "admin/actions.enable-binding": "Aktiver konfigurasjon ved binding",
  "admin/actions.binding-configurations": "Konfigurasjoner ved binding",
  "admin/actions.binding-id": "Bindings-ID",
  "admin/actions.binding-description": "Angi bindings-ID"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/fr.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Contexte de la recherche de produits",
  "admin/editor.product-search.maxItemsPerPage": "Nombre maximum d’articles par page",
  "admin/editor.product-search.hideUnavailableItems": "Masquer les articles non disponibles",
  "store/store.network-status.offline": "Pas de connexion Internet.",
  "admin/actions.enable-binding": "Permettre la configuration par liaison",
  "admin/actions.binding-configurations": "Configurations de liaison",
  "admin/actions.binding-id": "ID de liaison",
  "admin/actions.binding-description": "Saisir l'ID de la liaison"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/bg.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Контекст на продуктово търсене",
  "admin/editor.product-search.maxItemsPerPage": "Максимален брой артикули на страница",
  "admin/editor.product-search.hideUnavailableItems": "Скриване на недостъпните елементи",
  "store/store.network-status.offline": "Няма връзка с интернет.",
  "admin/actions.enable-binding": "Активиране на конфигурацията чрез обвързване",
  "admin/actions.binding-configurations": "Обвързващи конфигурации",
  "admin/actions.binding-id": "ID за обвързване",
  "admin/actions.binding-description": "Въведете ID за обвързване"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/ro.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Contextul de căutare a produselor",
  "admin/editor.product-search.maxItemsPerPage": "Numărul maxim de articole pe pagină",
  "admin/editor.product-search.hideUnavailableItems": "Ascunde articolele indisponibile",
  "store/store.network-status.offline": "Lipsă conexiune la internet.",
  "admin/actions.enable-binding": "Activează configurația prin legătură",
  "admin/actions.binding-configurations": "Configurații ale legăturii",
  "admin/actions.binding-id": "ID de legătură",
  "admin/actions.binding-description": "Introdu ID-ul de legătură"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/ca.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Context de cerca de productes",
  "admin/editor.product-search.maxItemsPerPage": "Nombre màxim d'articles per pàgina",
  "admin/editor.product-search.hideUnavailableItems": "Amaga els articles no disponibles",
  "store/store.network-status.offline": "Sense connexió a internet.",
  "admin/actions.enable-binding": "Activar la configuració per vinculació",
  "admin/actions.binding-configurations": "Configuració de vinculació",
  "admin/actions.binding-id": "ID d'enllaç",
  "admin/actions.binding-description": "Introduïu l'ID d'enllaç"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/context.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "admin/editor.product-search.title",
  "admin/editor.product-search.maxItemsPerPage": "admin/editor.product-search.maxItemsPerPage",
  "admin/editor.product-search.hideUnavailableItems": "Title of hideUnavailableItems prop",
  "store/store.network-status.offline": "store/store.network-status.offline",
  "admin/actions.enable-binding": "admin/actions.enable-binding",
  "admin/actions.binding-configurations": "admin/actions.binding-configurations",
  "admin/actions.binding-id": "admin/actions.binding-id",
  "admin/actions.binding-description": "admin/actions.binding-description"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/ko.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "제품 검색 컨텍스트",
  "admin/editor.product-search.maxItemsPerPage": "페이지당 최대 항목 수",
  "admin/editor.product-search.hideUnavailableItems": "이용할 수 없는 품목 숨기기",
  "store/store.network-status.offline": "인터넷 연결 없음.",
  "admin/actions.enable-binding": "바인딩하여 구성 활성화",
  "admin/actions.binding-configurations": "바인딩 구성",
  "admin/actions.binding-id": "바인딩 ID",
  "admin/actions.binding-description": "바인딩 ID 입력"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/no.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Produktsøk kontekst",
  "admin/editor.product-search.maxItemsPerPage": "Maksimalt antall varer per side",
  "admin/editor.product-search.hideUnavailableItems": "Skjul utilgjengelige varer",
  "store/store.network-status.offline": "Ingen Internett-forbindelse.",
  "admin/actions.enable-binding": "Aktiver konfigurasjon ved binding",
  "admin/actions.binding-configurations": "Konfigurasjoner ved binding",
  "admin/actions.binding-id": "Bindings-ID",
  "admin/actions.binding-description": "Angi bindings-ID"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/th.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "บริบทการค้นหาผลิตภัณฑ์",
  "admin/editor.product-search.maxItemsPerPage": "จำนวนสินค้าสูงสุดต่อหน้า",
  "admin/editor.product-search.hideUnavailableItems": "ซ่อนสินค้าที่ไม่พร้อมจำหน่าย",
  "store/store.network-status.offline": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต",
  "admin/actions.enable-binding": "เปิดใช้ค่ากำหนดด้วยการผูกค่า",
  "admin/actions.binding-configurations": "การกำหนดค่าการผูกข้อมูล",
  "admin/actions.binding-id": "รหัสการผูกข้อมูล",
  "admin/actions.binding-description": "ใส่รหัสการผูกข้อมูล"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/nn.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Produktsøk kontekst",
  "admin/editor.product-search.maxItemsPerPage": "Maksimalt antall varer per side",
  "admin/editor.product-search.hideUnavailableItems": "Skjul utilgjengelige varer",
  "store/store.network-status.offline": "Ingen Internett-forbindelse.",
  "admin/actions.enable-binding": "Aktiver konfigurasjon ved binding",
  "admin/actions.binding-configurations": "Konfigurasjoner ved binding",
  "admin/actions.binding-id": "Bindings-ID",
  "admin/actions.binding-description": "Angi bindings-ID"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/es.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "Contexto de búsqueda de productos",
  "admin/editor.product-search.maxItemsPerPage": "Número máximo de elementos por página",
  "admin/editor.product-search.hideUnavailableItems": "Esconder elementos no disponibles",
  "store/store.network-status.offline": "Sin conexión a internet.",
  "admin/actions.enable-binding": "Activar la configuración por vinculación",
  "admin/actions.binding-configurations": "Configuración de vinculación",
  "admin/actions.binding-id": "ID de vínculo",
  "admin/actions.binding-description": "Introduce el ID de vínculo"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/messages/ar.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.product-search.title": "سياق البحث عن المنتج",
  "admin/editor.product-search.maxItemsPerPage": "الحد الأقصى لعدد العناصر في كل صفحة",
  "admin/editor.product-search.hideUnavailableItems": "إخفاء العناصر غير المتاحة",
  "store/store.network-status.offline": "لا يوجد اتصال بالإنترنت.",
  "admin/actions.enable-binding": "Enable configuration by binding",
  "admin/actions.binding-configurations": "Binding configurations",
  "admin/actions.binding-id": "Binding ID",
  "admin/actions.binding-description": "Enter the binding ID"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/docs/README.md from the store VTEX app.

[Assistant]
Here's the implementation:

```markdown
# VTEX Store Framework
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

Framework that is used by all ecommerce stores build on VTEX IO.

⚠⚠ **All stores MUST use this app. Using a forked version WILL break your store.** ⚠⚠

## Table of Contents

- [Description](#description)
- [Release schedule](#release-schedule)
- [Store Builder](#store-builder)
  - [Overview](#overview)
  - [Blocks Language](#blocks-language)
  - [Interface Structure](#interface-structure)
  - [Recipes](#recipes)
- [Blocks Reference](#blocks-reference)
- [Pixel Architecture](#pixel-architecture)
- [Contributing](#contributing)

## Description

Store Framework is responsible for defining the basic structure of any ecommerce store of the platform. With this app, we want to provide an abstraction for our clients and partners not worry about SEO and fetch basic data from VTEX. Any account has this app installed.

This project has the following capabilities:

- Setup metatags for all pages.
- Fetch product and products search data from VTEX APIs
- Dispatch view events to analytics tools.
- Define the necessary interfaces and routes of the store.

## Release schedule

| Release |       Status        | Initial Release | Maintenance LTS Start | End-of-life | Store Compatibility |
| :-----: | :-----------------: | :-------------: | :-------------------: | :---------: | :-----------------: |
|  [2.x]  | **Current Release** |   2018-11-28    |                       |             |         2.x         |
|  [1.x]  | **Maintenance LTS** |   2018-08-21    |      2018-11-28       | March 2019  |         1.x         |

See our [LTS policy](https://github.com/vtex-apps/awesome-io#lts-policy) for more information.

## Store Builder

VTEX IO created a powerful way to configure the behavior [React](https://reactjs.org/) components yielding the basic building *blocks* for a web app.

IO **store builder** is a opinionated way to use IO capabilities to quickly build store components that can be reused
across ecommerce stores and interact seamlessly with its APIs and existing components.

### Overview

The Store builder allows you to extend existing blocks, like the ones provided by the Store Framework, allowing them to replace the blocks they extend via the VTEX IO Content Management System (CMS). They also allow you to build new blocks that provide functionality specific to your business needs and, then, create templates to insert those new blocks in your clients' ecommerce store while still benefiting from the continuous progress made by the native store components and it's extensions on the other parts of your store.

### Blocks Language

Blocks are instances of configured React components that follow a defined contract - or *interface*.
Blocks can be shared between apps and can contain other blocks. They can be used to create simple widgets
like buttons and forms, ready to use features like a review system or whole web pages.

To create web pages - or *templates*, a block must be acessible by a **route**. Routes associate blocks with paths that
can be used to match URLS. These **templates** are configurable in VTEX IO CMS.

Apps can also insert its blocks on specific page components as soon as the app is installed, via **plugins**.
Plugins provide an easy way to add specific functionality in a plug and play fashion to any store -
e.g. Visa Checkout button on the shopping cart, 360º image on the product galery.

To ensure that blocks would be reusable across stores, any VTEX IO store contain a set of *interfaces*
which blocks must implement. **Interfaces** are contracts that define the block component and which interfaces
it may contain, among other constraints.

The store builder validates and exports blocks, routes, interfaces and plugins defined in the app.
This allows the admin CMS and the store to use them. The configuration files which declares those
components must be in the `store/` folder on the root of the app.
The following sections we detail more about this concepts.

### Interface Structure
[TODO]
Explain interface structure, how it make stores "compatible" and its components reusable.

### Recipes
[TODO]

How to extend VTEX Store interfaces?

How to create a block / interface / route / plugin?

Examples, examples, examples...

## Blocks Reference

Please refer to [Blocks](./BLOCKS.md)

## Pixel Architecture

- Home: `homeView` event.

- Product: `productView` event.

- Department: `departmentView` event.

- Category: `categoryPath` event.

- Internal Site Search: `internalSiteSearchView` event.

- OrderPlaced Page: `orderPlaced` event.

- Other: `otherView` event.

### Enhanced Ecommerce

- Measuring Additions to a Shopping Cart: `addTocart` event.

- Measuring Removals from a Shopping Cart: `removeFromCart` event.

## Contributing

Check it out [how to contribute](https://github.com/vtex-apps/awesome-io#contributing) with this project.

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="https://github.com/gustavopvasconcellos"><img src="https://avatars1.githubusercontent.com/u/49173685?v=4" width="100px;" alt=""/><br /><sub><b>gustavopvasconcellos</b></sub></a><br /><a href="https://github.com/vtex-apps/store/commits?author=gustavopvasconcellos" title="Code">💻</a></td>
  </tr>
</table>

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/StoreWrapper.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
/* eslint-disable react/jsx-filename-extension */
import React, { Fragment, useEffect, useMemo } from 'react'
import {
  canUseDOM,
  ExtensionPoint,
  Helmet,
  NoSSR,
  useRuntime,
} from 'vtex.render-runtime'
import PropTypes from 'prop-types'
import { PixelProvider } from 'vtex.pixel-manager/PixelContext'
import { ToastProvider } from 'vtex.styleguide'
import { PWAProvider } from 'vtex.store-resources/PWAContext'
import { OrderQueueProvider } from 'vtex.order-manager/OrderQueue'
import { OrderItemsProvider } from 'vtex.order-items/OrderItems'
import { OrderFormProvider as OrderFormProviderCheckout } from 'vtex.order-manager/OrderForm'
import { ShippingOptionProvider } from 'vtex.shipping-option-components/ShippingOptionContext'

import UserDataPixel from './components/UserDataPixel'
import PageViewPixel from './components/PageViewPixel'
import OrderFormProvider from './components/OrderFormProvider'
import NetworkStatusToast from './components/NetworkStatusToast'
import WrapperContainer from './components/WrapperContainer'
import { normalizeNavigation } from './utils/navigation'
import { useCanonicalLink } from './hooks/useCanonicalLink'
import { VTEXAdsProvider } from './components/VTEXAdsProvider'

const APP_LOCATOR = 'vtex.store'
const CONTENT_TYPE = 'text/html; charset=utf-8'
const META_ROBOTS = 'index, follow'
const MOBILE_SCALING = 'width=device-width, initial-scale=1'
const CUSTOM_PAGE = 'store.custom'

const isSiteEditorIframe = () => {
  try {
    return (
      canUseDOM && window.top !== window.self && window.top.__provideRuntime
    )
  } catch {
    return false
  }
}

const getCustomPagesOpenGraph = ({ title, description, url }) => {
  return [
    { property: 'og:type', content: 'website' },
    { property: 'og:title', content: title },
    { property: 'og:url', content: url },
    { property: 'og:description', content: description },
  ]
}

const useFavicons = faviconLinks => {
  const { rootPath = '' } = useRuntime()
  if (!rootPath) {
    return faviconLinks
  }

  return (faviconLinks || []).map(favicon => {
    // Only fix if is relative path
    const { href } = favicon
    if (!href || href[0] !== '/') {
      return favicon
    }
    return { ...favicon, href: rootPath + href }
  })
}

const StoreWrapper = ({ children, CustomContext }) => {
  const {
    amp,
    culture: { country, locale, currency },
    route,
    route: { metaTags, title: pageTitle, rootName },
    getSettings,
    rootPath = '',
    prefetchDefaultPages,
    addNavigationRouteModifier,
  } = useRuntime()

  const supportsServiceWorker = canUseDOM && 'serviceWorker' in navigator

  useEffect(() => {
    prefetchDefaultPages([
      'store.custom',
      'store.product',
      'store.search',
      'store.search#brand',
      'store.search#category',
      'store.search#configurable',
      'store.search#custom',
      'store.search#department',
      'store.search#subcategory',
      'store.search#subcategory-terms',
    ])
  }, [prefetchDefaultPages])

  useEffect(() => {
    addNavigationRouteModifier(normalizeNavigation)
  }, [addNavigationRouteModifier])

  const settings = getSettings(APP_LOCATOR) || {}
  const {
    titleTag,
    metaTagDescription,
    metaTagRobots,
    storeName,
    faviconLinks,
    enableOrderFormOptimization = false,
    enableServiceWorker = true,
  } = settings

  const description = (metaTags && metaTags.description) || metaTagDescription
  const title = pageTitle || titleTag
  const robots = (metaTags || {}).robots || metaTagRobots

  const [queryMatch] = route.path.match(/\?.*/) || ['?']

  const canonicalLink = useCanonicalLink()

  const parsedFavicons = useFavicons(faviconLinks)

  const CustomContextElement = CustomContext || Fragment

  const isCustomPage = useMemo(() => rootName.includes(CUSTOM_PAGE), [rootName])

  const content = (
    <OrderQueueProvider>
      <OrderFormProviderCheckout>
        <OrderItemsProvider>
          <ShippingOptionProvider>
            <VTEXAdsProvider>
              <WrapperContainer className="vtex-store__template bg-base">
                <CustomContextElement>{children}</CustomContextElement>
              </WrapperContainer>
            </VTEXAdsProvider>
          </ShippingOptionProvider>
        </OrderItemsProvider>
      </OrderFormProviderCheckout>
    </OrderQueueProvider>
  )
  return (
    <Fragment>
      <Helmet
        title={title}
        meta={[
          ...(isCustomPage
            ? getCustomPagesOpenGraph({
                title,
                description,
                url: canonicalLink,
              })
            : []),
          // viewport meta tag is already handled in render-server for AMP pages
          !amp && { name: 'viewport', content: MOBILE_SCALING },
          { name: 'description', content: description },
          { name: 'copyright', content: storeName },
          { name: 'author', content: storeName },
          { name: 'country', content: country },
          { name: 'language', content: locale },
          { name: 'currency', content: currency },
          { name: 'robots', content: robots || META_ROBOTS },
          { name: 'storefront', content: 'store_framework' },
          { httpEquiv: 'Content-Type', content: CONTENT_TYPE },
        ]
          .filter(Boolean)
          .filter(meta => meta.content && meta.content.length > 0)}
        script={[
          supportsServiceWorker && {
            type: 'text/javascript',
            src: `${rootPath}/register.js${queryMatch}${
              enableServiceWorker ? '' : '&__disableSW=true'
            }&scope=${encodeURIComponent(rootPath)}`,
            defer: true,
          },
        ].filter(Boolean)}
        link={[
          ...(parsedFavicons || []),
          ...(!amp && canonicalLink
            ? [
                /* {
                    rel: 'amphtml',
                    href: encodeURI(`${canonicalLink}?amp`),
                  }, */
                {
                  rel: 'canonical',
                  href: encodeURI(canonicalLink),
                },
              ]
            : []),
        ].filter(Boolean)}
      />
      <PixelProvider currency={currency}>
        <PWAProvider rootPath={rootPath}>
          <PageViewPixel title={title} />
          <UserDataPixel />
          <ToastProvider positioning="window">
            <NetworkStatusToast />
            {enableOrderFormOptimization ? (
              content
            ) : (
              /** This is necessary for backwards compatibility, since stores
               *  might still need the OrderFormProvider from store-resources.
               *  If a store does not have `enableOrderFormOptimization` enabled,
               *  we should always add this provider.
               */
              <OrderFormProvider>{content}</OrderFormProvider>
            )}
          </ToastProvider>
        </PWAProvider>
      </PixelProvider>
      {isSiteEditorIframe() && (
        <NoSSR>
          <ExtensionPoint id="highlight-overlay" />
        </NoSSR>
      )}
    </Fragment>
  )
}

StoreWrapper.propTypes = {
  children: PropTypes.element,
  CustomContext: PropTypes.any,
}

export default StoreWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/ProductWrapper.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
import PropTypes from 'prop-types'
import React, { useMemo, Fragment } from 'react'
import {
  LoadingContextProvider,
  canUseDOM,
  useRuntime,
} from 'vtex.render-runtime'
import { ProductOpenGraph } from 'vtex.open-graph'
import useProduct from 'vtex.product-context/useProduct'
import ProductContextProvider from 'vtex.product-context/ProductContextProvider'
import { Product as ProductStructuredData } from 'vtex.structured-data'

import WrapperContainer from './components/WrapperContainer'
import ProductTitleAndPixel from './components/ProductTitleAndPixel'

const Content = ({ listName, loading, children, childrenProps }) => {
  const { product, selectedItem } = useProduct()
  return (
    <Fragment>
      <ProductTitleAndPixel
        listName={listName}
        product={product}
        selectedItem={selectedItem}
        loading={loading}
      />
      {product && <ProductOpenGraph />}
      {product && selectedItem && (
        <ProductStructuredData product={product} selectedItem={selectedItem} />
      )}
      {React.cloneElement(children, childrenProps)}
    </Fragment>
  )
}

const ProductWrapper = ({
  params: { slug, __listName: listName },
  productQuery,
  productQuery: { product, loading } = {},
  query,
  CustomContext,
  children,
  ...props
}) => {
  const { getSettings } = useRuntime()
  const { enableFullSSROnProduct } = getSettings('vtex.store')
  const childrenProps = useMemo(
    () => ({
      productQuery,
      slug,
      ...props,
    }),
    [productQuery, slug, props]
  )

  const hasProductData = !!product

  const loadingValue = useMemo(
    () => ({
      isParentLoading: loading || !hasProductData,
    }),
    [loading, hasProductData]
  )

  const isSSRLoading =
    loadingValue.isParentLoading && enableFullSSROnProduct && !canUseDOM

  const CustomContextElement = CustomContext || Fragment

  return (
    <WrapperContainer className="vtex-product-context-provider">
      <ProductContextProvider query={query} product={product}>
        <Content
          listName={listName}
          loading={loading}
          childrenProps={childrenProps}
        >
          <LoadingContextProvider value={loadingValue}>
            <CustomContextElement>
              {isSSRLoading ? <Fragment /> : children}
            </CustomContextElement>
          </LoadingContextProvider>
        </Content>
      </ProductContextProvider>
    </WrapperContainer>
  )
}

ProductWrapper.propTypes = {
  params: PropTypes.object,
  productQuery: PropTypes.object,
  children: PropTypes.node,
  /* URL query params */
  query: PropTypes.object,
  CustomContext: PropTypes.any,
}

export default ProductWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/ProfileChallenge.tsx from the store VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect, FC } from 'react'
import {
  useRuntime,
  canUseDOM,
  Loading,
  SessionResponse,
  Session,
} from 'vtex.render-runtime'

import { getSession } from './modules/session'

const loginPath = '/login'

const getLocation = () =>
  canUseDOM
    ? {
        url:
          window.location.pathname +
          window.location.search +
          window.location.hash,
        pathName: window.location.pathname,
      }
    : {
        url: (global as any).__pathname__,
        pathName: (global as any).__pathname__,
      }

const useSessionResponse = () => {
  const [session, setSession] = useState<SessionResponse>()
  const sessionPromise = getSession()

  useEffect(() => {
    if (!sessionPromise) {
      return
    }

    sessionPromise.then(sessionResponse => {
      const response = sessionResponse.response as SessionResponse

      setSession(response)
    })
  }, [sessionPromise])

  return session
}

function hasSession(session: SessionResponse | undefined): session is Session {
  return (
    session !== undefined &&
    session.type !== 'Unauthorized' &&
    session.type !== 'Forbidden'
  )
}

const useLoginRedirect = (isLoggedIn: boolean | null, page: string) => {
  const { rootPath = '' } = useRuntime()

  useEffect(() => {
    const { url, pathName } = getLocation()
    if (
      isLoggedIn === false &&
      page !== 'store.login' &&
      pathName !== loginPath &&
      canUseDOM
    ) {
      window.location.assign(
        `${rootPath}${loginPath}?returnUrl=${encodeURIComponent(url)}`
      )
    }
  }, [page, isLoggedIn, rootPath])
}

interface Props {
  page: string
}

const ProfileChallenge: FC<Props> = ({ children, page }) => {
  const session = useSessionResponse()
  const isLoggedIn = hasSession(session)
    ? session.namespaces?.profile?.isAuthenticated?.value === 'true'
    : null

  useLoginRedirect(isLoggedIn, page)

  // isLoggedIn null means that we still don't know, session is loading
  if (isLoggedIn === null) {
    return (
      <div className="flex justify-center ma4">
        <Loading />
      </div>
    )
  }

  if (isLoggedIn === false) {
    return null
  }

  return <>{children}</>
}

export default ProfileChallenge

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/HomeWrapper.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { useMemo, Fragment } from 'react'
import PropTypes from 'prop-types'
import { useRuntime, canUseDOM } from 'vtex.render-runtime'
import SearchAction from 'vtex.structured-data/SearchAction'
import { HomeOpenGraph } from 'vtex.open-graph'

import useDataPixel from './hooks/useDataPixel'

const HomeWrapper = ({ children }) => {
  const { account, route, getSettings } = useRuntime()
  const { searchTermPath } = getSettings('vtex.store')

  const pixelEvents = useMemo(() => {
    if (!canUseDOM) {
      return null
    }

    return [
      {
        event: 'pageInfo',
        eventType: 'homeView',
        accountName: account,
        pageTitle: document.title,
        // eslint-disable-next-line no-restricted-globals
        pageUrl: location.href,
        pageCategory: 'Home',
      },
    ]
  }, [account])

  useDataPixel(pixelEvents, route.routeId)

  return (
    <Fragment>
      <SearchAction searchTermPath={searchTermPath} />
      <HomeOpenGraph />
      {children}
    </Fragment>
  )
}

HomeWrapper.propTypes = {
  children: PropTypes.element,
}

export default HomeWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/SearchWrapper.tsx from the store VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, {
  Fragment,
  useState,
  useMemo,
  useEffect,
  FC,
  ReactElement,
  ComponentType,
} from 'react'
import {
  Helmet,
  useRuntime,
  LoadingContextProvider,
  canUseDOM,
  RuntimeWithRoute,
  StoreSettings,
} from 'vtex.render-runtime'
import { SearchOpenGraph } from 'vtex.open-graph'
import { ProductList as ProductListStructuredData } from 'vtex.structured-data'
import queryString from 'query-string'

import { capitalize } from './modules/capitalize'
import useDataPixel from './hooks/useDataPixel'
import { usePageView } from './components/PageViewPixel'
import {
  getDepartmentMetadata,
  getCategoryMetadata,
  getSearchMetadata,
} from './modules/searchMetadata'
import { SearchQuery } from './modules/searchTypes'
import { PixelEvent } from './typings/event'
import { useCanonicalLink } from './hooks/useCanonicalLink'

const APP_LOCATOR = 'vtex.store'

interface SearchRouteParams {
  term?: string
  department?: string
  category?: string
}

const pageCategory = (products: unknown[], params: SearchRouteParams) => {
  if (!products || products.length === 0) {
    return 'EmptySearch'
  }
  const { category, term } = params
  return term ? 'InternalSiteSearch' : category ? 'Category' : 'Department'
}

type PageEventName =
  | 'internalSiteSearchView'
  | 'categoryView'
  | 'departmentView'
  | 'emptySearchView'

const mapEvent = {
  InternalSiteSearch: 'internalSiteSearchView',
  Category: 'categoryView',
  Department: 'departmentView',
  EmptySearch: 'emptySearchView',
}
const fallbackView = 'otherView'

const getPageEventName = (
  products: unknown[],
  params: SearchRouteParams
): PageEventName => {
  if (!products) {
    return fallbackView as PageEventName
  }

  const category = pageCategory(products, params)

  return (mapEvent[category] || fallbackView) as PageEventName
}

const getDecodeURIComponent = (encodedURIComponent: string) => {
  try {
    return decodeURIComponent(encodedURIComponent)
  } catch {
    return encodedURIComponent
  }
}

interface GetTitleTagParams {
  titleTag: string
  storeTitle: string
  term?: string
  pageTitle?: string
  pageNumber?: number
  removeStoreNameTitle?: boolean
}

const getTitleTag = ({
  titleTag,
  storeTitle,
  term,
  pageTitle,
  pageNumber = 0,
  removeStoreNameTitle,
}: GetTitleTagParams) => {
  /*
  titleNumber and storeTitleFormatted depend on the value of enablePageNumberTitle and removeStoreNameTitle params,
  by default, the value of enablePageNumberTitle and removeStoreNameTitle is false, only if the value of these
  parameters is true, it will affect the value of titleNumber or storeTitleFormatted
  */
  const titleNumber = pageNumber > 0 ? ` #${pageNumber}` : ''
  const storeTitleFormatted = removeStoreNameTitle ? '' : ` - ${storeTitle}`

  if (titleTag) {
    return `${getDecodeURIComponent(
      titleTag
    )}${titleNumber}${storeTitleFormatted}`
  }

  if (pageTitle) {
    return `${getDecodeURIComponent(
      pageTitle
    )}${titleNumber}${storeTitleFormatted}`
  }

  if (term) {
    return `${capitalize(
      getDecodeURIComponent(term)
    )}${titleNumber}${storeTitleFormatted}`
  }

  return storeTitle
}

const getSearchIdentifier = (
  searchQuery: SearchQuery,
  orderBy?: string,
  page?: string
) => {
  const { variables } = searchQuery

  if (!variables) {
    return
  }
  const { query, map } = variables
  return query + map + (orderBy ?? '') + (page ?? '')
}

interface GetSearchCanonicalParams {
  canonicalLink: string
  page?: number
  map?: string
  term?: string
}

function shouldNotIncludeMap(map?: string) {
  if (!map || map === 'b' || map === 'brand') {
    return true
  }

  const mapTree = map.split(',')

  if (mapTree.length > 4) {
    return false
  }

  return mapTree.every(mapItem => mapItem === 'c')
}

function getSearchCanonical({
  canonicalLink,
  page,
  map,
  term,
}: GetSearchCanonicalParams) {
  if (page !== null && page !== undefined && page < 1) {
    return null
  }

  const query = {
    page: page !== undefined && page !== null && page > 1 ? page : undefined,
    map: shouldNotIncludeMap(map) ? undefined : map,
    _q: term,
  }

  const canonicalWithPage = queryString.stringifyUrl({
    url: decodeURI(canonicalLink),
    query,
  })

  return canonicalWithPage
}

interface GetHelmetLinkParams {
  canonicalLink: string | null
  page: number
  map?: string
  term?: string
  rel: 'canonical' | 'prev' | 'next'
}

export function getHelmetLink({
  canonicalLink,
  page,
  map,
  rel,
  term,
}: GetHelmetLinkParams) {
  if (!canonicalLink) {
    return null
  }

  let pageAfterTransformation = 0

  if (rel === 'canonical') {
    pageAfterTransformation = page
  } else if (rel === 'next') {
    pageAfterTransformation = page + 1
  } else if (rel === 'prev') {
    pageAfterTransformation = page - 1
  }

  const canonicalWithParams = getSearchCanonical({
    canonicalLink,
    page: pageAfterTransformation,
    map,
    term,
  })

  if (!canonicalWithParams) {
    return null
  }

  return {
    rel,
    href: canonicalWithParams,
  }
}

function isNotLastPage(
  products: SearchQuery['products'],
  to: number | undefined,
  recordsFiltered: number | undefined
) {
  if (
    !products ||
    to === undefined ||
    to === null ||
    recordsFiltered === undefined ||
    recordsFiltered === null
  ) {
    return null
  }

  return to + 1 < recordsFiltered
}

interface AppliedFilters {
  name: string
}

interface SearchPageInfoEvent {
  department?: DepartmentMetadata | null
  category?: CategoryMetadata | null
  search?: SearchMetadata | null
  orderBy?: string
  page?: string
  appliedFilters?: AppliedFilters[]
}

interface DepartmentMetadata {
  id: string
  name: string
}

interface CategoryMetadata {
  id: string
  name: string
}

interface SearchMetadata {
  term?: string
  category: CategoryMetadata | null
  results: number
}

interface SearchWrapperProps {
  children: ReactElement
  params: SearchRouteParams
  searchQuery: SearchQuery
  orderBy?: string
  to?: number
  page?: number
  maxItemsPerPage?: number
  CustomContext?: ComponentType
  facetsLoading?: boolean
}

const SearchWrapper: FC<SearchWrapperProps> = props => {
  const {
    params,
    orderBy,
    searchQuery,
    facetsLoading,
    searchQuery: {
      variables: { map } = {},
      data: {
        searchMetadata: { titleTag = '', metaTagDescription = '' } = {},
        productSearch: { recordsFiltered = undefined } = {},
      } = {},
    } = {},
    CustomContext,
    page: pageFromQuery = 0,
    to,
    maxItemsPerPage,
    children,
  } = props
  const {
    account,
    getSettings,
    query: { page, _q: termFromQuery },
    route: { title: pageTitle, metaTags },
  } = useRuntime() as RuntimeWithRoute

  const settings = getSettings(APP_LOCATOR) || ({} as StoreSettings)
  const loading = searchQuery ? searchQuery.loading : undefined
  const {
    titleTag: defaultStoreTitle,
    storeName,
    enablePageNumberTitle = false,
    canonicalWithoutUrlParams = false,
    removeStoreNameTitle = false,
  } = settings

  const title = getTitleTag({
    titleTag,
    storeTitle: storeName || defaultStoreTitle,
    term: params.term,
    pageTitle,
    pageNumber: enablePageNumberTitle ? Number(page) : 0,
    removeStoreNameTitle,
  })

  const canonicalLink = useCanonicalLink()

  const helmetCanonicalLink = getHelmetLink({
    canonicalLink,
    page: pageFromQuery,
    map: canonicalWithoutUrlParams ? '' : map,
    term: termFromQuery,
    rel: 'canonical',
  })

  const openGraphParams = {
    title,
    description: metaTagDescription || metaTags?.description,
    canonical: helmetCanonicalLink?.href,
  }

  const pixelEvents = useMemo(() => {
    if (
      !searchQuery ||
      !canUseDOM ||
      !searchQuery.products ||
      !searchQuery.data?.facets?.queryArgs ||
      facetsLoading
    ) {
      return null
    }

    const { products } = searchQuery

    const event = getPageEventName(products, params)
    const pageInfoEvent: SearchPageInfoEvent & PixelEvent = {
      event: 'pageInfo',
      eventType: event,
      accountName: account,
      pageTitle: title,
      pageUrl: window.location.href,
      orderBy,
      appliedFilters: map?.split(',').map(name => ({ name })),
      page,
      category: searchQuery?.data
        ? getCategoryMetadata(searchQuery.data)
        : null,
      department: searchQuery?.data
        ? getDepartmentMetadata(searchQuery.data)
        : null,
      search: searchQuery?.data
        ? getSearchMetadata(searchQuery.data, pageFromQuery, maxItemsPerPage)
        : null,
    }

    return [
      pageInfoEvent,
      {
        event,
        products,
      },
    ]
  }, [
    searchQuery,
    facetsLoading,
    params,
    account,
    title,
    orderBy,
    map,
    page,
    pageFromQuery,
    maxItemsPerPage,
  ])

  const [hasLoaded, setHasLoaded] = useState(true)

  const loadingValue = useMemo(
    () => ({
      isParentLoading: loading && hasLoaded,
    }),
    [loading, hasLoaded]
  )

  const pixelCacheKey = getSearchIdentifier(searchQuery, orderBy, page)
  usePageView({ title, cacheKey: pixelCacheKey })
  useDataPixel(pixelEvents, pixelCacheKey, loading)

  /** Prevents the loader from showing up after initial data is loaded,
   * e.g. when setQuery changes the query variables */
  useEffect(() => {
    if (!loading) {
      setHasLoaded(false)
    }
  }, [loading])

  const CustomContextElement = CustomContext ?? Fragment
  return (
    <Fragment>
      <Helmet
        title={title}
        meta={[
          params.term && {
            name: 'robots',
            content: 'noindex,follow',
          },
          metaTagDescription && {
            name: 'description',
            content: metaTagDescription,
          },
        ].filter(Boolean)}
        link={[
          helmetCanonicalLink,
          getHelmetLink({
            canonicalLink,
            page: pageFromQuery,
            map,
            rel: 'prev',
          }),
          isNotLastPage(searchQuery.products, to, recordsFiltered)
            ? getHelmetLink({
                canonicalLink,
                page: pageFromQuery,
                map,
                rel: 'next',
              })
            : null,
        ].filter(Boolean)}
      />

      <ProductListStructuredData products={searchQuery.products} />
      <SearchOpenGraph meta={openGraphParams} />
      <LoadingContextProvider value={loadingValue}>
        <CustomContextElement>
          {React.cloneElement(children, props)}
        </CustomContextElement>
      </LoadingContextProvider>
    </Fragment>
  )
}

export default SearchWrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/cacheLocator.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
import { buildCacheLocator } from 'vtex.render-runtime'

const SEARCH_GRAPHQL = 'vtex.search-graphql@0.x'

export const cacheLocator = {
  product: slug => buildCacheLocator(SEARCH_GRAPHQL, 'Product', slug),
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/ContentPageContext.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
// This context simplifies the check for content pages
const ContentPageContext = ({ children }) => children

export default ContentPageContext

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/ProductContext.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
/* eslint-disable no-restricted-imports */
import PropTypes from 'prop-types'
import React, { useEffect, useMemo } from 'react'
import { withApollo, graphql, compose } from 'react-apollo'
import { isEmpty } from 'ramda'
import { useRuntime } from 'vtex.render-runtime'
import product from 'vtex.store-resources/QueryProduct'
import productPreviewFragment from 'vtex.store-resources/QueryProductPreviewFragment'
import productBenefits from 'vtex.store-resources/QueryProductBenefits'
import productCategoryTree from 'vtex.store-resources/QueryUNSTABLEProductCategoryTree'

import { cacheLocator } from './cacheLocator'

const EMPTY_OBJECT = {}

const emptyOrNull = value => (value != null ? isEmpty(value) : true)

const getInfoFromQuery = (queryObj = {}) => {
  const { product: productFromQuery, loading = true } = queryObj
  return !loading && productFromQuery ? productFromQuery : EMPTY_OBJECT
}

const useProduct = ({
  catalog,
  productBenefits: productBenefitsQueryResult,
  categoryTree,
}) => {
  const catalogInfo = getInfoFromQuery(catalog)
  const benefitsInfo = getInfoFromQuery(productBenefitsQueryResult)
  const categoryTeeInfo = getInfoFromQuery(categoryTree)

  return useMemo(() => {
    const allEmpty = [catalogInfo, benefitsInfo, categoryTeeInfo].every(
      emptyOrNull
    )
    return allEmpty
      ? null
      : { ...catalogInfo, ...benefitsInfo, ...categoryTeeInfo }
  }, [benefitsInfo, catalogInfo, categoryTeeInfo])
}

function getLoading(props) {
  const { catalog: { loading: catalogLoading = true } = {} } = props
  return catalogLoading
}

function useNotFound(loading, propsProduct, slug) {
  const { navigate } = useRuntime()

  useEffect(() => {
    if (!propsProduct && !loading) {
      navigate({
        page: 'store.search',
        params: { term: slug },
        query: `productLinkNotFound=${slug}`,
      })
    }
  }, [loading, propsProduct, navigate, slug])
}

const ProductContext = _props => {
  const {
    params,
    params: { slug },
    client,
    catalog: { refetch },
    ...props
  } = _props

  const loading = getLoading(_props)
  const propsProduct = useProduct(_props)

  useNotFound(loading, propsProduct, slug)

  const productPreview = client.readFragment({
    id: cacheLocator.product(slug),
    fragment: productPreviewFragment,
  })

  const productToQueryFor =
    propsProduct ||
    (productPreview && productPreview.items ? productPreview : null)

  const productQuery = useMemo(
    () => ({
      loading,
      product: productToQueryFor,
      refetch,
      error:
        !productToQueryFor && !loading
          ? {
              message: 'Product not found!',
            }
          : null,
    }),
    [loading, productToQueryFor, refetch]
  )

  const childrenProps = useMemo(
    () => ({
      productQuery,
      slug,
      params,
    }),
    [productQuery, slug, params]
  )

  return React.cloneElement(props.children, childrenProps)
}

ProductContext.propTypes = {
  params: PropTypes.object,
  query: PropTypes.shape({
    skuId: PropTypes.string,
  }),
  data: PropTypes.object,
  children: PropTypes.node,
  client: PropTypes.object,
  catalog: PropTypes.object,
  productBenefits: PropTypes.object,
}

const catalogOptions = {
  name: 'catalog',
  options: props => ({
    variables: {
      slug: props.params.slug,
      skipCategoryTree: true,
      identifier: {
        field: 'id',
        value: props.params.id || '',
      },
    },
    errorPolicy: 'all',
  }),
}

const productBenefitsOptions = {
  name: 'productBenefits',
  options: props => ({
    variables: {
      slug: props.params.slug,
      identifier: {
        field: 'id',
        value: props.params.id || '',
      },
    },
    errorPolicy: 'all',
    ssr: false,
  }),
}

const categoryTreeOptions = {
  name: 'categoryTree',
  options: props => ({
    variables: {
      slug: props.params.slug,
      identifier: {
        field: 'id',
        value: props.params.id || '',
      },
    },
    errorPolicy: 'all',
    ssr: false,
  }),
}

export default compose(
  withApollo,
  graphql(product, catalogOptions),
  graphql(productBenefits, productBenefitsOptions),
  graphql(productCategoryTree, categoryTreeOptions)
)(ProductContext)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/package.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "private": true,
  "scripts": {
    "test": "vtex-test-tools test",
    "lint": "eslint --ext js,jsx,ts,tsx ."
  },
  "dependencies": {
    "@vtex/ads-react": "0.3.1",
    "hoist-non-react-statics": "^3.0.1",
    "prop-types": "^15.5.10",
    "query-string": "^7.0.1",
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.4",
    "@types/jest": "^24.0.18",
    "@types/ramda": "^0.26.21",
    "@vtex/test-tools": "^3.4.3",
    "@vtex/tsconfig": "^0.3.0",
    "apollo-client-preset": "^1.0.8",
    "graphql": "^0.13.0",
    "graphql-tag": "^2.7.3",
    "prettier": "^1.19.1",
    "react": "^16.2.0",
    "react-apollo": "^3.1.5",
    "react-dom": "^16.2.0",
    "react-intl": "3.9.1",
    "typescript": "3.9.7",
    "vtex.blog-interfaces": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.blog-interfaces@0.0.6/public/@types/vtex.blog-interfaces",
    "vtex.login": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.login@2.28.0/public/_types/react",
    "vtex.my-account": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.my-account@1.13.2/public/@types/vtex.my-account",
    "vtex.open-graph": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.open-graph@1.0.5/public/@types/vtex.open-graph",
    "vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.7.0/public/@types/vtex.order-items",
    "vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.4/public/@types/vtex.order-manager",
    "vtex.pixel-interfaces": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-interfaces@1.1.1/public/_types/react",
    "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.1.4/public/@types/vtex.pixel-manager",
    "vtex.product-context": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-context@0.7.1/public/@types/vtex.product-context",
    "vtex.product-review-interfaces": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-review-interfaces@1.0.2/public/_types/react",
    "vtex.product-specification-badges": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-specification-badges@0.1.1/public/@types/vtex.product-specification-badges",
    "vtex.pwa-components": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pwa-components@0.4.1/public/@types/vtex.pwa-components",
    "vtex.pwa-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pwa-graphql@1.15.1/public/@types/vtex.pwa-graphql",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.99.0/public/@types/vtex.render-runtime",
    "vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.9.0/public/@types/vtex.rich-text",
    "vtex.search-result": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-result@3.55.1/public/_types/react",
    "vtex.store-footer": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-footer@2.20.1/public/@types/vtex.store-footer",
    "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.120.0/public/@types/vtex.store-graphql",
    "vtex.store-header": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-header@2.25.5/public/_types/react",
    "vtex.store-indexer": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-indexer@0.12.0/public/_types/react",
    "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.55.0/public/_types/react",
    "vtex.structured-data": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.structured-data@0.3.2/public/@types/vtex.structured-data",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.113.0/public/@types/vtex.styleguide",
    "vtex.telemarketing": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.telemarketing@2.10.1/public/@types/vtex.telemarketing"
  },
  "resolutions": {
    "json-schema": "^0.4.0",
    "jsdom": "^16.5.0",
    "jest-environment-jsdom": "^26.0.0",
    "node-notifier": "^8.0.1"
  },
  "version": "2.145.0"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/Fold.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'

const Fold = () => <React.Fragment />

export default Fold

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/DefaultChallenge.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
const DefaultChallenge = ({ children }) => {
  return children
}

export default DefaultChallenge

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/SearchContext.jsx from the store VTEX app.

[Assistant]
Here's the implementation:

```jsx
/* eslint-disable no-restricted-imports */
import PropTypes from 'prop-types'
import { path } from 'ramda'
import React from 'react'
import { useRuntime } from 'vtex.render-runtime'
import SearchQuery from 'vtex.search-result/SearchQuery'

import { initializeMap, SORT_OPTIONS } from './modules/search'
import { VTEXAdsProvider } from './components/VTEXAdsProvider'

const DEFAULT_MAX_ITEMS_PER_PAGE = 10

const trimStartingSlash = value => value && value.replace(/^\//, '')

const SearchContext = props => {
  const {
    nextTreePath,
    params,
    maxItemsPerPage = DEFAULT_MAX_ITEMS_PER_PAGE,
    queryField,
    mapField,
    orderByField,
    hideUnavailableItems,
    facetsBehavior = 'Static',
    __unstableCategoryTreeBehavior = 'default',
    skusFilter,
    simulationBehavior,
    installmentCriteria,
    excludedPaymentSystems,
    includedPaymentSystems,
    sponsoredProductsBehavior = 'sync',
    query: {
      order: orderBy = orderByField || SORT_OPTIONS[0].value,
      page: pageQuery,
      map: mapQuery,
      priceRange,
      // backwards-compatibility
      rest,
      fuzzy,
      operator,
      searchState,
    },
    children,
    __unstableProductOriginVtex,
  } = props

  const {
    page: runtimePage,
    query: runtimeQuery,
    route: {
      queryString: { map: renderMap },
    },
  } = useRuntime()

  const fieldsFromQueryString = {
    mapField: runtimeQuery.map,
    queryField: trimStartingSlash(runtimeQuery.query),
  }

  const areFieldsFromQueryStringValid = !!(
    fieldsFromQueryString.mapField && fieldsFromQueryString.queryField
  )

  const map = areFieldsFromQueryStringValid
    ? fieldsFromQueryString.mapField
    : renderMap || mapQuery || initializeMap(params)

  // Remove params which don't compose a search path
  const { id, ...searchParams } = params
  const query = Object.values(searchParams)
    .filter(term => term && term.length > 0)
    .join('/')
    .replace(/\/\//g, '/') // This cleans some bad cases of two // on some terms.

  const getCorrectQueryValue = () => {
    let queryValue = query

    // Checks if this is on the format of preventRouteChange and get the correct data
    if (areFieldsFromQueryStringValid) {
      queryValue = fieldsFromQueryString.queryField
    }

    // Normal query format, without preventRouteChange
    else if (queryField) {
      queryValue = queryField
    }

    // Legacy search
    else if (rest && rest.length > 0) {
      queryValue = `${query}/${rest.replace(',', '/')}`
    }

    try {
      return decodeURI(queryValue)
    } catch {
      return queryValue
    }
  }

  const queryValue = getCorrectQueryValue()
  const mapValue = queryField ? mapField : map
  const state =
    (typeof sessionStorage !== 'undefined' &&
      sessionStorage.getItem('searchState')) ||
    searchState

  return (
    <VTEXAdsProvider>
      <SearchQuery
        maxItemsPerPage={maxItemsPerPage}
        query={queryValue}
        map={mapValue}
        orderBy={orderBy}
        priceRange={priceRange}
        hideUnavailableItems={hideUnavailableItems}
        facetsBehavior={facetsBehavior}
        categoryTreeBehavior={__unstableCategoryTreeBehavior}
        pageQuery={pageQuery}
        skusFilter={skusFilter}
        simulationBehavior={simulationBehavior}
        installmentCriteria={installmentCriteria}
        excludedPaymentSystems={excludedPaymentSystems}
        includedPaymentSystems={includedPaymentSystems}
        operator={operator}
        fuzzy={fuzzy}
        searchState={state}
        __unstableProductOriginVtex={__unstableProductOriginVtex}
        sponsoredProductsBehavior={sponsoredProductsBehavior}
      >
        {(searchQuery, extraParams) => {
          return React.cloneElement(children, {
            searchQuery: {
              ...searchQuery,
              // backwards-compatibility
              data: {
                ...(searchQuery.data || {}),
                products: path(
                  ['data', 'productSearch', 'products'],
                  searchQuery
                ),
              },
              facets: path(['data', 'facets'], searchQuery),
              products: path(
                ['data', 'productSearch', 'products'],
                searchQuery
              ),
              recordsFiltered: path(
                ['data', 'productSearch', 'recordsFiltered'],
                searchQuery
              ),
            },
            searchContext: runtimePage,
            pagesPath: nextTreePath,
            map,
            orderBy,
            priceRange,
            page: extraParams.page,
            from: extraParams.from,
            to: extraParams.to,
            facetsLoading: extraParams.facetsLoading,
            maxItemsPerPage,
            // backwards-compatibility
            rest,
            lazyItemsRemaining: extraParams.lazyItemsRemaining,
          })
        }}
      </SearchQuery>
    </VTEXAdsProvider>
  )
}

SearchContext.propTypes = {
  /** Route parameters */
  params: PropTypes.shape({
    category: PropTypes.string,
    department: PropTypes.string,
    term: PropTypes.string,
    id: PropTypes.string,
  }),
  /** Query params */
  query: PropTypes.shape({
    map: PropTypes.string,
    page: PropTypes.string,
    order: PropTypes.oneOf(SORT_OPTIONS.map(o => o.value)),
    priceRange: PropTypes.string,
    rest: PropTypes.any,
    operator: PropTypes.string,
    fuzzy: PropTypes.string,
    searchState: PropTypes.string,
  }),
  /** Custom query `query` param */
  queryField: PropTypes.string,
  /** Custom query `map` param */
  mapField: PropTypes.string,
  /** Custom query `orderBy` param */
  orderByField: PropTypes.string,
  /** Current extension point name */
  nextTreePath: PropTypes.string,
  /** Component to be rendered */
  children: PropTypes.node.isRequired,
  /** Max items to show per result page */
  maxItemsPerPage: PropTypes.number,
  hideUnavailableItems: PropTypes.bool,
  facetsBehavior: PropTypes.string,
  __unstableCategoryTreeBehavior: PropTypes.string,
  skusFilter: PropTypes.string,
  simulationBehavior: PropTypes.string,
  installmentCriteria: PropTypes.string,
  excludedPaymentSystems: PropTypes.string,
  includedPaymentSystems: PropTypes.string,
  __unstableProductOriginVtex: PropTypes.bool,
  sponsoredProductsBehavior: PropTypes.string,
}

SearchContext.schema = {
  title: 'admin/editor.product-search.title',
  type: 'object',
  properties: {
    maxItemsPerPage: {
      title: 'admin/editor.product-search.maxItemsPerPage',
      type: 'number',
    },
    queryField: {
      title: 'Query',
      type: 'string',
    },
    mapField: {
      title: 'Map',
      type: 'string',
    },
    orderByField: {
      title: 'Order by field',
      type: 'string',
      default: SORT_OPTIONS[0].value,
      enum: SORT_OPTIONS.map(opt => opt.value),
      enumNames: SORT_OPTIONS.map(opt => opt.label),
    },
    hideUnavailableItems: {
      title: 'admin/editor.product-search.hideUnavailableItems',
      type: 'boolean',
      default: false,
    },
    sponsoredProductsBehavior: {
      title: 'Sponsored products behavior',
      type: 'string',
      default: 'sync',
    },
  },
}

export default SearchContext

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/store/contentSchemas.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "definitions": {
    "StoreSettings": {
      "title": "VTEX Store",
      "type": "object",
      "properties": {
        "storeName": {
          "title": "Store Name",
          "type": "string"
        },
        "requiresAuthorization": {
          "title": "Enables B2B behavior",
          "type": "boolean"
        },
        "titleTag": {
          "title": "Default title tag",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "metaTagDescription": {
          "title": "Meta description tag",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "metaTagRobots": {
          "title": "Meta robots tag",
          "type": "string",
          "description": "Default value: index, follow"
        },
        "faviconLinks": {
          "title": "Favicons",
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "rel": {
                "title": "Favicon Relationship",
                "type": "string",
                "description": "This favicon relationship, e.g: 'icon', 'shortcut icon', 'apple-touch-icon'"
              },
              "type": {
                "title": "Favicon Media Type",
                "type": "string",
                "description": "(Optional) Favicon type, e.g: image/png"
              },
              "sizes": {
                "title": "Favicon Size",
                "type": "string",
                "pattern": "^[0-9]+x[0-9]+$",
                "description": "(Optional) Favicon size, format: {width}x{height} e.g: 180x180"
              },
              "href": {
                "title": "Favicon href",
                "type": "string"
              }
            },
            "required": ["rel", "href"]
          },
          "description": "Configure your store's favicons"
        },
        "searchTermPath": {
          "title": "Search Term Path",
          "type": "string",
          "description": "Indicate the search path of your store"
        },
        "advancedSettings": {
          "title": "Advanced Store settings",
          "type": "object",
          "properties": {
            "enableOrderFormOptimization": {
              "title": "Enable orderForm optimization",
              "type": "boolean",
              "default": false,
              "description": "This setting disables the legacy orderForm provider. More at: https://vtex.io/docs/recipes/store-management/enabling-order-form-optimization."
            },
            "fetchSponsoredProductsOnSearch": {
              "title": "[BETA] Fetch sponsored products in search results",
              "type": "boolean",
              "default": false,
              "description": "If this store's account has configured VTEX Ads, this option enables the fetching of sponsored products within search results."
            },
            "a11ySemanticHtmlMigration": {
              "title": "Enable accessibility semantic HTML migration",
              "type": "boolean",
              "default": false,
              "description": "Enables semantic HTML improvements for accessibility that may introduce breaking changes. Components will use proper HTML elements like <label>, <main>, <nav> etc."
            },
            "publisherId": {
              "title": "VTEX Ads Publisher ID",
              "type": "string",
              "default": "",
              "description": "Publisher ID used by VTEX Ads to identify your store. It is used to display ads on your store."
            }
          }
        },
        "enablePageNumberTitle": {
          "title": "Enable page number in meta title",
          "type": "boolean",
          "description": "Add a #{Number} to the end of the title to avoid the title duplication issue."
        },
        "canonicalWithoutUrlParams": {
          "title": "Canonical url without url params",
          "type": "boolean",
          "description": "Remove map parameter from canonical url. May cause issues when going to a page with facets selected. Test with caution after turning it on."
        },
        "removeStoreNameTitle": {
          "title": "Remove store name from title",
          "type": "boolean",
          "description": "Remove store name at the end of Product and Category meta titles."
        }
      }
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/store/blocks.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.search#brand": {
    "blocks": ["search-result"]
  },
  "store.search#department": {
    "blocks": ["search-result"]
  },
  "store.search#category": {
    "blocks": ["search-result"]
  },
  "store.search#subcategory": {
    "blocks": ["search-result"]
  },
  "store.search#subcategory-terms": {
    "blocks": ["search-result"]
  },
  "store.search#custom": {
    "blocks": ["search-result"]
  },
  "store.search#configurable": {
    "blocks": ["search-result"]
  },
  "rich-text#not-found": {
    "props": {
      "textAlignment": "CENTER",
      "textPosition": "CENTER",
      "text": "**PAGE NOT FOUND**",
      "font": "t-heading-1"
    }
  },
  "store.not-found#product": {
    "blocks": ["rich-text#not-found"]
  },
  "store.not-found#search": {
    "blocks": ["rich-text#not-found"]
  },
  "store.custom": {
    "parent": {
      "header": "header.full"
    }
  },
  "store.offline": {
    "blocks": ["offline-warning"]
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/store/interfaces.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store": {
    "allowConditions": true,
    "component": "*",
    "around": ["storeWrapper", "challenge"],
    "before": ["header.full"],
    "after": ["footer", "pixels"],
    "preview": {
      "type": "transparent",
      "height": 600
    }
  },
  "store.home": {
    "around": ["homeWrapper"],
    "preview": {
      "type": "box",
      "height": 1400
    }
  },
  "store.product": {
    "around": ["productWrapper"],
    "before": ["header.full"],
    "context": "ProductContext",
    "preview": {
      "type": "box",
      "height": 800
    }
  },
  "store.search": {
    "around": ["searchWrapper"],
    "context": "SearchContext",
    "preview": {
      "type": "grid",
      "height": 1400
    }
  },
  "store.account": {
    "required": ["my-account"],
    "around": ["challenge.profile"],
    "preview": {
      "type": "text",
      "height": 800
    }
  },
  "store.login": {
    "required": ["vtex.login:login-content"],
    "preview": {
      "type": "spinner",
      "height": 600
    }
  },
  "store.orderplaced": {
    "preview": {
      "type": "spinner",
      "height": 600
    }
  },
  "store.product-review-form": {
    "preview": {
      "type": "spinner",
      "height": 800
    }
  },
  "store.blog-home": {
    "before": ["header.full"]
  },
  "store.blog-category": {
    "before": ["header.full"],
    "required": ["blog-category-list"]
  },
  "store.blog-post": {
    "before": ["header.full"],
    "required": ["blog-post-details"]
  },
  "store.blog-search-result": {
    "before": ["header.full"],
    "required": ["blog-search-list"]
  },
  "store.not-found": {
    "preview": {
      "type": "box",
      "height": 800
    }
  },
  "storeWrapper": {
    "allowed": ["highlight-overlay"],
    "component": "StoreWrapper"
  },
  "homeWrapper": {
    "component": "HomeWrapper"
  },
  "productWrapper": {
    "component": "ProductWrapper"
  },
  "searchWrapper": {
    "component": "SearchWrapper"
  },
  "challenge": {
    "component": "DefaultChallenge",
    "extensible": "public"
  },
  "highlight-overlay": {
    "component": "*",
    "extensible": "vtex"
  },
  "challenge.profile": {
    "component": "ProfileChallenge"
  },
  "promo-bar": {
    "component": "*"
  },
  "store.custom": {},
  "store.content": {
    "context": "ContentPageContext"
  },
  "store.offline": {
    "required": ["offline-warning"]
  },
  "__fold__": {
    "component": "Fold"
  },
  "__fold__.mobile": {},
  "__fold__.desktop": {},
  "__fold__.experimentalLazyImages": {},
  "__fold__.experimentalLazyAssets": {}
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/store/routes.json from the store VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.home": {
    "path": "/"
  },
  "store.account": {
    "path": "/account"
  },
  "store.login": {
    "path": "/login"
  },
  "store.product": {
    "path": "/_v/segment/routing/vtex.store@2.x/product/:id/:slug/p",
    "canonical": "/:slug/p",
    "contentType": "product"
  },
  "store.search": {
    "path": "/:term/s",
    "canonical": "/:term",
    "contentType": "search"
  },
  "store.search#brand": {
    "path": "/_v/segment/routing/vtex.store@2.x/brand/:id/:brand(/*terms)",
    "canonical": "/:brand",
    "map": ["b"],
    "contentType": "brand"
  },
  "store.search#department": {
    "path": "/_v/segment/routing/vtex.store@2.x/department/:id/:department(/*terms)",
    "canonical": "/:department",
    "map": ["c"],
    "contentType": "department"
  },
  "store.search#category": {
    "path": "/_v/segment/routing/vtex.store@2.x/category/:id/:department/:category(/*terms)",
    "canonical": "/:department/:category",
    "map": ["c", "c"],
    "contentType": "category"
  },
  "store.search#subcategory": {
    "path": "/_v/segment/routing/vtex.store@2.x/subcategory/:id/:department/:category/:subcategory(/*terms)",
    "canonical": "/:department/:category/:subcategory",
    "map": ["c", "c", "c"],
    "contentType": "subcategory"
  },
  "store.search#configurable": {
    "path": "/s/*terms"
  },
  "store.orderplaced": {
    "path": "/checkout/orderPlaced"
  },
  "store.offline": {
    "path": "/_v/offline"
  },
  "store.custom": {
    "path": "/_v/segment/routing/vtex.store@2.x/userRoute/:id(/*terms)",
    "contentType": "userRoute",
    "canonical": "/*terms"
  },
  "store.not-found#product": {
    "path": "/_v/segment/routing/vtex.store@2.x/notFoundProduct/:id/:slug/p",
    "canonical": "/:slug/p",
    "contentType": "notFoundProduct"
  },
  "store.not-found#search": {
    "path": "/_v/segment/routing/vtex.store@2.x/notFoundSearch/:id/*terms",
    "canonical": "/*terms",
    "contentType": "notFoundSearch"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/images/SearchIcon.jsx from the store VTEX app.

[Assistant]
Here's the implementation:

```jsx
import React from 'react'

const SearchIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 16 16"
    width="18"
    height="18"
  >
    <path
      d="M12.7,11.3c0.9-1.2,1.4-2.6,1.4-4.2C14.1,3.2,11,0,7.1,0S0,3.2,0,7.1c0,3.9,3.2,7.1,7.1,7.1 c1.6,0,3.1-0.5,4.2-1.4l3,3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L12.7,11.3z M7.1,12.1 C4.3,12.1,2,9.9,2,7.1S4.3,2,7.1,2s5.1,2.3,5.1,5.1S9.9,12.1,7.1,12.1z"
      className="nc-icon-wrapper"
      fill="#368df7"
    />
  </svg>
)

export default SearchIcon

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/images/VTEXIcon.jsx from the store VTEX app.

[Assistant]
Here's the implementation:

```jsx
import React from 'react'

const VTEXIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 1566 800"
    width="100"
    height="50"
  >
    <g className="nc-icon-wrapper" fill="#FFF">
      <path d="M657.59 186.14h-374c-29 0-47.57 30.83-34 56.46L287 313.44h-67.82A24.94 24.94 0 0 0 197.12 350l120.33 227.75a24.94 24.94 0 0 0 44.08 0l32.68-61.52 41 77.62c14.43 27.3 53.52 27.35 68 .08l187.46-352.76c13.25-24.95-4.83-55.03-33.08-55.03zm-168 150.72L408.76 489a16.6 16.6 0 0 1-29.33 0l-80.05-151.5A16.6 16.6 0 0 1 314 313.13h161.33a16.15 16.15 0 0 1 14.26 23.73z" />
      <path d="M1055.39 349.79h-40.91V490a4.83 4.83 0 0 1-4.82 4.82h-31.55a4.83 4.83 0 0 1-4.82-4.82V349.79h-41.15a4.63 4.63 0 0 1-4.82-4.58v-24.8a4.63 4.63 0 0 1 4.82-4.58h123.24a4.84 4.84 0 0 1 5.06 4.58v24.81a4.84 4.84 0 0 1-5.05 4.57z" />
      <path d="M1186.72 493.81c-8.43 1.2-22.61 3.13-48.62 3.13-31.07 0-58.52-7.95-58.52-51.78v-80c0-43.83 27.7-51.54 58.76-51.54 26 0 39.95 1.93 48.38 3.13 3.37.48 4.82 1.69 4.82 4.82V344a4.83 4.83 0 0 1-4.82 4.82h-50.78c-11.32 0-15.41 3.85-15.41 16.38v21.92h64.27a4.83 4.83 0 0 1 4.82 4.82v22.88a4.83 4.83 0 0 1-4.82 4.82h-64.27v25.53c0 12.52 4.09 16.38 15.41 16.38h50.78a4.83 4.83 0 0 1 4.82 4.82v22.4c0 3.11-1.45 4.56-4.82 5.04z" />
      <path d="M1368.43 494.77h-38.29c-3.13 0-4.58-1-6.26-3.61l-33.2-52.71L1260.6 490c-1.69 2.89-3.37 4.82-6 4.82h-35.64c-2.41 0-3.61-1.45-3.61-3.13a4.47 4.47 0 0 1 .48-1.69l52.17-87-52.71-82.61a3.42 3.42 0 0 1-.48-1.45 3.47 3.47 0 0 1 3.61-3.13h38.77c2.65 0 4.58 2.41 6 4.58l30.81 48.65 29.82-48.65c1.2-2.17 3.37-4.58 6-4.58h35.64a3.47 3.47 0 0 1 3.61 3.13 3.42 3.42 0 0 1-.48 1.45l-52.45 83.12 54.7 86.49a5.38 5.38 0 0 1 .72 2.41c.01 1.4-1.2 2.36-3.13 2.36z" />
      <path d="M869.6 316.31a3.72 3.72 0 0 0-3.64 3L831 448.7c-.48 2.65-1.2 3.61-3.37 3.61s-2.89-1-3.37-3.61l-35-129.42a3.72 3.72 0 0 0-3.64-3h-34.41a3.72 3.72 0 0 0-3.62 4.56s42.7 148.39 43.17 149.85c5.7 17.68 19.53 26.13 37.13 26.13 16.76 0 31.39-8.85 37.11-26.08.68-2 42.43-149.91 42.43-149.91a3.72 3.72 0 0 0-3.62-4.55z" />
      <path d="M657.59 186.14h-374c-29 0-47.57 30.83-34 56.46L287 313.44h-67.82A24.94 24.94 0 0 0 197.12 350l120.33 227.75a24.94 24.94 0 0 0 44.08 0l32.68-61.52 41 77.62c14.43 27.3 53.52 27.35 68 .08l187.46-352.76c13.25-24.95-4.83-55.03-33.08-55.03zm-168 150.72L408.76 489a16.6 16.6 0 0 1-29.33 0l-80.05-151.5A16.6 16.6 0 0 1 314 313.13h161.33a16.15 16.15 0 0 1 14.26 23.73z" />
    </g>
  </svg>
)

export default VTEXIcon

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/typings/vtex.render-runtime.d.ts from the store VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.render-runtime' {
  interface Runtime {
    account: string
    rootPath: string
    query: Record<string, string>
    navigate: (args: NavigateArgs) => void
    getSettings(id: string): StoreSettings
    route: {
      routeId: string
    }
  }

  interface RuntimeWithRoute extends Runtime {
    route: {
      routeId: string
      title?: string
      metaTags?: MetaTagsParams
      canonicalPath?: string
    }
  }

  interface MetaTagsParams {
    description: string
    keywords: string[]
  }

  interface NavigateArgs {
    fallbackToWindowLocation: boolean
    to: string
  }

  interface StoreSettings {
    storeName: string
    titleTag: string
    enablePageNumberTitle: boolean
    canonicalWithoutUrlParams: boolean
    removeStoreNameTitle: boolean
    a11ySemanticHtmlMigration: boolean
    publisherId: string
  }

  interface KeyValue {
    value: string
  }

  interface Session {
    id: string
    type: undefined
    namespaces: {
      store: {
        channel: string
      }
      profile: {
        isAuthenticated: KeyValue
        email: string
      }
    }
  }

  interface SessionUnauthorized {
    type: 'Unauthorized'
    message: string
  }

  interface SessionForbidden {
    type: 'Forbidden'
    message: string
  }

  export interface RenderSession {
    sessionPromise: Promise<SessionPromise>
  }

  export interface SessionPromise {
    response: SessionResponse
  }

  export type SessionResponse = Session | SessionUnauthorized | SessionForbidden

  export function useRuntime(): Runtime
  export const Helmet
  export const canUseDOM: boolean
  export const LoadingContextProvider
}

export {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/typings/global.d.ts from the store VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Window extends Window {
  dataLayer: any[]
  __hostname__: string | undefined
}

declare module 'vtex.store-resources/QueryProductSearchV3' {
  const query: any
  export default query
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/typings/vtex.pixel-manager.d.ts from the store VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.pixel-manager/PixelContext' {
  interface Pixel {
    push(data: unknown): void
  }

  export function usePixel(): Pixel
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/typings/event.ts from the store VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PixelEvent {
  event: string
  eventType: string
  accountName: string
  pageTitle: string
  pageUrl: string
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/utils/navigation.js from the store VTEX app.

[Assistant]
Here's the implementation:

```javascript
/* eslint-disable no-restricted-globals */
// eslint-disable-next-line no-restricted-imports
import { contains, path as ramdaPath, zip } from 'ramda'
import queryString from 'query-string'

const SPEC_FILTER = 'specificationFilter'
const MAP_CATEGORY_CHAR = 'c'
const MAP_VALUES_SEP = ','
const PATH_SEPARATOR = '/'
const INTELLIGENT_SEARCH_BRAND = 'brand'

const isLegacySearchFormat = (pathSegments, map) => {
  if (!map) {
    return false
  }
  return map.split(MAP_VALUES_SEP).length === pathSegments.length
}

const categoriesInSequence = mapValues => {
  let count = 0
  for (const value of mapValues) {
    if (value !== MAP_CATEGORY_CHAR) {
      return count
    }
    count++
  }
  return count
}

const queryMapComparator = (tuple1, tuple2) => {
  const [, specFilterVal1] = tuple1 && tuple1[0].split(`${SPEC_FILTER}_`)
  const [, specFilterVal2] = tuple2 && tuple2[0].split(`${SPEC_FILTER}_`)
  const [facetName1, facetValue1] = tuple1
  const [facetName2, facetValue2] = tuple2

  const intelligentSearchCategoryRegex = /category-[0-9]+/
  const isISCategory1 = intelligentSearchCategoryRegex.test(facetName1)
  const isISCategory2 = intelligentSearchCategoryRegex.test(facetName2)
  const isISBrand1 = facetName1 === INTELLIGENT_SEARCH_BRAND
  const isISBrand2 = facetName2 === INTELLIGENT_SEARCH_BRAND

  // Makes the URL in the IS have the following order:
  // /[category hierarchy/alphabetically]/[brand alphabetically]/[specs alphabetically]
  // Example: category-1/category-2/brand/spec1/spec2
  if (isISCategory1 && !isISCategory2) {
    return -1
  }
  if (isISCategory2 && !isISCategory1) {
    return 1
  }
  if (isISCategory1 && isISCategory2) {
    return (
      facetName1.localeCompare(facetName2) ||
      facetValue1.localeCompare(facetValue2)
    )
  }
  if (isISBrand1 && !isISBrand2) {
    return -1
  }
  if (isISBrand2 && !isISBrand1) {
    return 1
  }

  const considerSpecificationFilter =
    specFilterVal1 &&
    specFilterVal2 &&
    !isNaN(Number(specFilterVal1)) &&
    !isNaN(Number(specFilterVal2))

  return considerSpecificationFilter
    ? Number(specFilterVal1) -
        Number(specFilterVal2) +
        facetValue1.localeCompare(facetValue2)
    : facetValue1.localeCompare(facetValue2)
}

const normalizeQueryMap = (pathSegments, mapSegments) => {
  const categoryTreeDepth = categoriesInSequence(mapSegments)
  const zippedMapQuery = zip(mapSegments, pathSegments)

  const sorted =
    zippedMapQuery &&
    zippedMapQuery.slice(categoryTreeDepth).sort(queryMapComparator)

  const assembledSortedQuery = zippedMapQuery
    .slice(0, categoryTreeDepth)
    .concat(sorted)

  const sortedMap = assembledSortedQuery
    .map(value => (Array.isArray(value) ? value[0] : value))
    .join(',')
  const sortedPathSegments = assembledSortedQuery.map(tuple => tuple[1])

  return {
    map: sortedMap,
    pathSegments: sortedPathSegments,
  }
}

const normalizeSearchNavigation = (pathSegments, map) => {
  return {
    pathSegments,
    map,
  }
}

const normalizeLegacySearchNavigation = (pathSegments, queryMap, query) => {
  if (queryMap.map) {
    const mapValues = queryMap.map.split(MAP_VALUES_SEP)
    let convertedSegments = zip(
      pathSegments,
      mapValues
    ).map(([pathSegment, mapValue]) =>
      contains(SPEC_FILTER, mapValue) ? pathSegment : pathSegment.toLowerCase()
    )

    const {
      pathSegments: sortedPathSegments,
      map: sortedMap,
    } = normalizeQueryMap(
      queryMap.query ? queryMap.query.split('/').slice(1) : convertedSegments,
      mapValues
    )

    queryMap.map = sortedMap
    if (queryMap.query) {
      queryMap.query = `/${sortedPathSegments.join('/')}`
    } else {
      convertedSegments = sortedPathSegments
    }

    const normalizedQuery = queryString.stringify(queryMap, {
      encode: false,
    })

    return { pathSegments: convertedSegments, query: normalizedQuery }
  }
  return { pathSegments, query }
}

export const normalizeNavigation = navigation => {
  if (ramdaPath(['__RUNTIME__', 'route', 'domain'], window) !== 'store') {
    return navigation
  }

  const { path, query } = navigation
  const parsedQuery = query ? queryString.parse(query) : {}
  const { map } = parsedQuery

  const pathSegments = path.startsWith(PATH_SEPARATOR)
    ? path.split(PATH_SEPARATOR).slice(1)
    : path.split(PATH_SEPARATOR)

  const normalizedNavigation =
    parsedQuery.query || isLegacySearchFormat(pathSegments, map)
      ? normalizeLegacySearchNavigation(pathSegments, parsedQuery, query)
      : normalizeSearchNavigation(pathSegments, query)

  navigation.path = path.startsWith('/')
    ? `/${normalizedNavigation.pathSegments.join('/')}`
    : normalizedNavigation.pathSegments.join('/')
  navigation.query = normalizedNavigation.query
  return navigation
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/components/ProductTitleAndPixel.tsx from the store VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable no-restricted-imports */
import React, { useMemo, FC } from 'react'
import { Helmet, useRuntime, canUseDOM } from 'vtex.render-runtime'
import { path } from 'ramda'

import useDataPixel from '../hooks/useDataPixel'
import { usePageView } from './PageViewPixel'
import { PixelEvent } from '../typings/event'
import { useCanonicalLink } from '../hooks/useCanonicalLink'

const titleSeparator = ' - '

const STORE_APP = 'vtex.store'

interface Product {
  linkText: string
  productName: string
  brand: string
  brandId: string
  categoryId: string
  categories: string[]
  categoryTree: Category[]
  productId: string
  titleTag: string
  metaTagDescription: string
  productReference: string
  items: SKU[]
}

interface ProductViewEvent {
  detailUrl: string
  brand: string
  brandId: string
  productReference: string
  linkText: string
  categoryId: string
  categories: string[]
  categoryTree: Category[]
  productId: string
  productName: string
  items: SKUEvent[]
  selectedSku: SKUEvent
}

interface Category {
  id: string
  name: string
}

interface SKUEvent extends Omit<SKU, 'images'> {
  imageUrl: string
}

interface SKU {
  itemId: string
  ean: string
  name: string
  images: Image[]
  referenceId: [{ Value: string }]
  sellers: Seller[]
}

interface Image {
  imageId: string
  imageLabel: string
  imageUrl: string
}

interface Seller {
  commertialOffer: CommertialOffer
  sellerId: string
  sellerName: string
  sellerDefault: boolean
}

interface CommertialOffer {
  ListPrice: number
  Price: number
  AvailableQuantity: number
  PriceWithoutDiscount: number
}

type MaybeProduct = Product | null

function usePageInfo(
  titleTag: string,
  product: MaybeProduct,
  loading: boolean
) {
  const { account } = useRuntime()

  const pageEvents = useMemo(() => {
    if (!product || !canUseDOM) {
      return []
    }

    const pageInfo: PixelEvent = {
      event: 'pageInfo',
      eventType: 'productView',
      accountName: account,
      pageTitle: titleTag,
      pageUrl: window.location.href,
    }

    return pageInfo
  }, [account, product, titleTag])

  useDataPixel(pageEvents, path(['linkText'], product), loading)
}

function getSkuProperties(item: SKU): SKUEvent {
  return {
    itemId: item.itemId,
    name: item.name,
    ean: item.ean,
    referenceId: item.referenceId,
    imageUrl:
      item.images && item.images.length > 0 ? item.images[0].imageUrl : '',
    sellers: item.sellers.map(seller => ({
      sellerId: seller.sellerId,
      sellerName: seller.sellerName,
      sellerDefault: seller.sellerDefault,
      commertialOffer: {
        Price: seller.commertialOffer.Price,
        ListPrice: seller.commertialOffer.ListPrice,
        AvailableQuantity: seller.commertialOffer.AvailableQuantity,
        PriceWithoutDiscount:
          seller.commertialOffer?.PriceWithoutDiscount ||
          seller.commertialOffer.Price,
      },
    })),
  }
}

interface UseProductEventsParams {
  product: Product
  selectedItem: SKU
  loading: boolean
  listName?: string
}

function useProductEvents({
  product,
  selectedItem,
  loading,
  listName,
}: UseProductEventsParams) {
  const productEvents = useMemo(() => {
    const hasCategoryTree = Boolean(product?.categoryTree?.length)

    if (!product || !canUseDOM || !selectedItem || !hasCategoryTree) {
      return []
    }

    const eventProduct: ProductViewEvent = {
      detailUrl: `/${product.linkText}/p`,
      brand: product.brand,
      brandId: product.brandId,
      productReference: product.productReference,
      linkText: product.linkText,
      categoryId: product.categoryId,
      categories: product.categories,
      categoryTree: product.categoryTree,
      productId: product.productId,
      productName: product.productName,
      items: product.items.map(getSkuProperties),
      selectedSku: getSkuProperties(selectedItem),
    }

    return [
      {
        event: 'productView',
        product: eventProduct,
        list: listName,
      },
    ]
  }, [product, selectedItem, listName])

  // When linkText or selectedItem changes, it will trigger the productEvents
  const pixelCacheKey = `${product?.linkText}${selectedItem?.itemId}`

  useDataPixel(productEvents, pixelCacheKey, loading)
}

function useTitle(product: Product) {
  const { getSettings } = useRuntime()
  const { titleTag = undefined, productName = undefined } = product || {}
  let title = titleTag ?? productName ?? ''

  const settings = getSettings(STORE_APP)

  if (settings?.removeStoreNameTitle === false) {
    const { storeName, titleTag: storeTitleTag } = settings
    const storeData = storeName || storeTitleTag
    if (storeData) {
      title += title ? titleSeparator + storeData : storeData
    }
  }

  return title
}

interface UseProductCanonicalLinkParams {
  linkText?: string
}

function useProductCanonicalLink({ linkText }: UseProductCanonicalLinkParams) {
  const canonicalLink = useCanonicalLink()

  if (!canonicalLink) {
    return null
  }

  const rel = 'canonical'

  if (!linkText) {
    return {
      rel,
      href: encodeURI(canonicalLink),
    }
  }

  const lowerCaseLinkText = linkText.toLowerCase()
  const lowerCaseCanonical = canonicalLink.toLowerCase()

  const linkTextIndexOnCanonical = lowerCaseCanonical.lastIndexOf(
    lowerCaseLinkText
  )

  if (linkTextIndexOnCanonical === -1) {
    return {
      rel,
      href: encodeURI(canonicalLink),
    }
  }

  const canonicalBase = canonicalLink.substring(0, linkTextIndexOnCanonical)

  const canonicalEnd = canonicalLink.substring(
    linkTextIndexOnCanonical + linkText.length
  )

  const appropriateCanonical = `${canonicalBase}${linkText}${canonicalEnd}`

  return {
    rel,
    href: encodeURI(appropriateCanonical),
  }
}

interface Props {
  listName?: string
  product: Product
  selectedItem: SKU
  loading: boolean
}

const ProductTitleAndPixel: FC<Props> = ({
  product,
  selectedItem,
  loading,
  listName,
}) => {
  const { metaTagDescription = undefined } = product || {}
  const title = useTitle(product)

  const pixelCacheKey = path<string>(['linkText'], product)
  usePageView({
    title,
    skip: pixelCacheKey === undefined,
    cacheKey: pixelCacheKey,
  })
  usePageInfo(title, product, loading)
  useProductEvents({ product, selectedItem, loading, listName })

  const productCanonical = useProductCanonicalLink({
    linkText: product?.linkText,
  })

  return (
    <Helmet
      title={title}
      meta={[
        metaTagDescription && {
          name: 'description',
          content: metaTagDescription,
        },
      ].filter(Boolean)}
      link={[productCanonical].filter(Boolean)}
    />
  )
}

export default ProductTitleAndPixel

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store/react/components/UserDataPixel.tsx from the store VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useEffect, FC } from 'react'
import { usePixel } from 'vtex.pixel-manager/PixelContext'

import {
  getSessionPromiseFromWindow,
  getUserData,
  SessionResponse,
} from '../hooks/getUserData'

const UserDataPixel: FC = () => {
  const { push } = usePixel()

  useEffect(() => {
    getSessionPromiseFromWindow().then((data: SessionResponse) => {
      const profileFields = data?.response?.namespaces?.profile

      if (!profileFields) {
        return
      }

      const userData = getUserData(profileFields)

      push({
        event: 'userData',
        ...userData,
      })
    })
  }, [push])

  return null
}

export default UserDataPixel

```