@faststore/core 3.98.0-dev.2 → 3.98.0-dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +40 -40
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/server-production/0.pack +0 -0
  8. package/.next/cache/webpack/server-production/index.pack +0 -0
  9. package/.next/prerender-manifest.js +1 -1
  10. package/.next/prerender-manifest.json +1 -1
  11. package/.next/react-loadable-manifest.json +17 -17
  12. package/.next/routes-manifest.json +1 -1
  13. package/.next/server/chunks/3890.js +2 -2
  14. package/.next/server/chunks/4803.js +1 -1
  15. package/.next/server/chunks/7371.js +1 -1
  16. package/.next/server/chunks/948.js +1 -1
  17. package/.next/server/chunks/9563.js +3 -3
  18. package/.next/server/chunks/9853.js +1 -1
  19. package/.next/server/functions-config-manifest.json +1 -1
  20. package/.next/server/middleware-build-manifest.js +1 -1
  21. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  22. package/.next/server/pages/[...slug].js +1 -1
  23. package/.next/server/pages/api/graphql.js +3 -3
  24. package/.next/server/pages/en-US/404.html +2 -2
  25. package/.next/server/pages/en-US/404.json +1 -1
  26. package/.next/server/pages/en-US/500.html +2 -2
  27. package/.next/server/pages/en-US/500.json +1 -1
  28. package/.next/server/pages/en-US/checkout.html +2 -2
  29. package/.next/server/pages/en-US/checkout.json +1 -1
  30. package/.next/server/pages/en-US/login.html +2 -2
  31. package/.next/server/pages/en-US/login.json +1 -1
  32. package/.next/server/pages/en-US/s.html +2 -2
  33. package/.next/server/pages/en-US/s.json +1 -1
  34. package/.next/server/pages/en-US.html +2 -2
  35. package/.next/server/pages/en-US.json +1 -1
  36. package/.next/server/pages/s.js +1 -1
  37. package/.next/server/pages-manifest.json +1 -1
  38. package/.next/static/chunks/2284.922fe939dafb3b2d.js +1 -0
  39. package/.next/static/chunks/{2927.23bae2c79f0ac0f3.js → 2927.5a79877943a6bf7c.js} +1 -1
  40. package/.next/static/chunks/3399.72d28af405858825.js +1 -0
  41. package/.next/static/chunks/{7191-5ede6e7ef625ea77.js → 7191-4bf7ddfc2bd0f3a9.js} +1 -1
  42. package/.next/static/chunks/9173-ddb551c7ca3de40b.js +1 -0
  43. package/.next/static/chunks/9465.a1858c778b1083b9.js +1 -0
  44. package/.next/static/chunks/{UIToast.de15325248043ce5.js → UIToast.19a8664c01a00d3a.js} +1 -1
  45. package/.next/static/chunks/pages/[...slug]-52db16871a86e9bd.js +1 -0
  46. package/.next/static/chunks/pages/_app-c7470c325e07d4ce.js +1 -0
  47. package/.next/static/chunks/{webpack-345c083b2f1f8bb9.js → webpack-1947faa4988b2d76.js} +1 -1
  48. package/.next/static/{J4h39ytIYFua-E1SZRYO9 → zYBmCmAclx4jsVX0yAK0w}/_buildManifest.js +1 -1
  49. package/.next/trace +140 -140
  50. package/.turbo/turbo-build.log +12 -12
  51. package/.turbo/turbo-test.log +6 -6
  52. package/@generated/gql.ts +14 -6
  53. package/@generated/graphql.ts +88 -8
  54. package/@generated/persisted-documents.json +3 -2
  55. package/@generated/schema.graphql +2 -0
  56. package/CHANGELOG.md +6 -0
  57. package/package.json +4 -4
  58. package/src/components/product/ProductGrid/ProductGrid.tsx +26 -1
  59. package/src/components/search/SearchDropdown/SearchDropdown.tsx +11 -2
  60. package/src/components/search/SearchInput/SearchInput.tsx +2 -0
  61. package/src/components/templates/ProductListingPage/ProductListing.tsx +1 -1
  62. package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +17 -0
  63. package/src/sdk/product/usePageProductsQuery.ts +11 -9
  64. package/src/sdk/search/useSuggestions.ts +1 -0
  65. package/.next/static/chunks/2284.dffe7b0e5a5bfb4a.js +0 -1
  66. package/.next/static/chunks/3399.3e1f685c992c345b.js +0 -1
  67. package/.next/static/chunks/9173-ab3c4d9d8f978c4b.js +0 -1
  68. package/.next/static/chunks/9465.e09b81f7e6195587.js +0 -1
  69. package/.next/static/chunks/pages/[...slug]-3579b3b8b8309552.js +0 -1
  70. package/.next/static/chunks/pages/_app-1595678557980d65.js +0 -1
  71. /package/.next/static/{J4h39ytIYFua-E1SZRYO9 → zYBmCmAclx4jsVX0yAK0w}/_ssgManifest.js +0 -0
@@ -1,23 +1,23 @@
1
1
 
2
- > @faststore/core@3.98.0-dev.1 prebuild /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.98.0-dev.2 prebuild /home/runner/work/faststore/faststore/packages/core
3
3
  > na run partytown && na run generate
4
4
 
5
5
 
6
- > @faststore/core@3.98.0-dev.1 partytown /home/runner/work/faststore/faststore/packages/core
6
+ > @faststore/core@3.98.0-dev.2 partytown /home/runner/work/faststore/faststore/packages/core
7
7
  > partytown copylib ./public/~partytown
8
8
 
9
9
  Partytown lib copied to: /home/runner/work/faststore/faststore/packages/core/public/~partytown
10
10
 
11
- > @faststore/core@3.98.0-dev.1 generate /home/runner/work/faststore/faststore/packages/core
11
+ > @faststore/core@3.98.0-dev.2 generate /home/runner/work/faststore/faststore/packages/core
12
12
  > na run generate:schema && na run generate:codegen && na run format:generated
13
13
 
14
14
 
15
- > @faststore/core@3.98.0-dev.1 generate:schema /home/runner/work/faststore/faststore/packages/core
15
+ > @faststore/core@3.98.0-dev.2 generate:schema /home/runner/work/faststore/faststore/packages/core
16
16
  > tsx src/server/generator/generateGraphQLSchemaFile.ts
17
17
 
18
18
  Schema GraphQL file generated successfully
19
19
 
20
- > @faststore/core@3.98.0-dev.1 generate:codegen /home/runner/work/faststore/faststore/packages/core
20
+ > @faststore/core@3.98.0-dev.2 generate:codegen /home/runner/work/faststore/faststore/packages/core
21
21
  > graphql-codegen
22
22
 
23
23
  [STARTED] Parse Configuration
@@ -37,11 +37,11 @@ Running lifecycle hook "afterStart" scripts...
37
37
  [CLI] Loading Documents
38
38
  [CLI] Generating output
39
39
 
40
- > @faststore/core@3.98.0-dev.1 format:generated /home/runner/work/faststore/faststore/packages/core
40
+ > @faststore/core@3.98.0-dev.2 format:generated /home/runner/work/faststore/faststore/packages/core
41
41
  > prettier --write "@generated/**/*.{ts,js,tsx,jsx,json}" --loglevel error
42
42
 
43
43
 
44
- > @faststore/core@3.98.0-dev.1 build /home/runner/work/faststore/faststore/packages/core
44
+ > @faststore/core@3.98.0-dev.2 build /home/runner/work/faststore/faststore/packages/core
45
45
  > next build
46
46
 
47
47
  ⚠ No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache
@@ -91,8 +91,8 @@ Route (pages) Size First Load JS
91
91
  ┌ ● / 7.39 kB 147 kB
92
92
  ├ └ css/02259c549b2179f2.css 3.1 kB
93
93
  ├ /_app 0 B 108 kB
94
- ├ ● /[...slug] 2.55 kB 157 kB
95
- ├ ● /[slug]/p 98.2 kB 237 kB
94
+ ├ ● /[...slug] 2.56 kB 157 kB
95
+ ├ ● /[slug]/p 98.2 kB 238 kB
96
96
  ├ └ css/a6a4ebbe01adbbad.css 22.2 kB
97
97
  ├ ○ /404 1.57 kB 141 kB
98
98
  ├ ● /500 1.57 kB 141 kB
@@ -107,7 +107,7 @@ Route (pages) Size First Load JS
107
107
  ├ ● /pvt/account/[...unknown] 287 B 108 kB
108
108
  ├ λ /pvt/account/403 2.98 kB 142 kB
109
109
  ├ └ css/0fae3d432331aae9.css 4.68 kB
110
- ├ λ /pvt/account/404 2.18 kB 141 kB
110
+ ├ λ /pvt/account/404 2.18 kB 142 kB
111
111
  ├ └ css/0fc6b2ff69142c6a.css 4.74 kB
112
112
  ├ λ /pvt/account/orders 9.78 kB 149 kB
113
113
  ├ └ css/40a294d0a24ad01d.css 14.1 kB
@@ -123,8 +123,8 @@ Route (pages) Size First Load JS
123
123
  + First Load JS shared by all 111 kB
124
124
  ├ chunks/framework-d514426edf885c68.js 45.4 kB
125
125
  ├ chunks/main-ec03882c4375091d.js 33.2 kB
126
- ├ chunks/pages/_app-1595678557980d65.js 25.1 kB
127
- ├ chunks/webpack-345c083b2f1f8bb9.js 3.85 kB
126
+ ├ chunks/pages/_app-c7470c325e07d4ce.js 25.1 kB
127
+ ├ chunks/webpack-1947faa4988b2d76.js 3.85 kB
128
128
  └ css/0f070d03aacd9cc5.css 3.57 kB
129
129
 
130
130
  λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
@@ -1,16 +1,16 @@
1
1
 
2
- > @faststore/core@3.98.0-dev.1 test /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.98.0-dev.2 test /home/runner/work/faststore/faststore/packages/core
3
3
  > jest
4
4
 
5
- PASS test/utils/multipleTemplates.test.ts (28.012 s)
6
- PASS test/utils/clearCookies.test.ts (27.964 s)
7
- PASS test/server/cms/global.test.ts
5
+ PASS test/utils/multipleTemplates.test.ts (27.896 s)
6
+ PASS test/utils/clearCookies.test.ts (27.577 s)
8
7
  PASS test/utils/cookieCacheBusting.test.ts
8
+ PASS test/server/cms/global.test.ts
9
9
  PASS test/server/cms/index.test.ts
10
- PASS test/server/index.test.ts (33.083 s)
10
+ PASS test/server/index.test.ts (31.317 s)
11
11
 
12
12
  Test Suites: 6 passed, 6 total
13
13
  Tests: 47 passed, 47 total
14
14
  Snapshots: 0 total
15
- Time: 34.323 s
15
+ Time: 32.499 s
16
16
  Ran all test suites.
package/@generated/gql.ts CHANGED
@@ -72,17 +72,19 @@ const documents = {
72
72
  types.ClientProductCountQueryDocument,
73
73
  '\n query ClientAllVariantProductsQuery($locator: [IStoreSelectedFacet!]!) {\n product(locator: $locator) {\n ...ProductSKUMatrixSidebarFragment_product\n }\n }\n':
74
74
  types.ClientAllVariantProductsQueryDocument,
75
- '\n query ClientManyProductsQuery(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n $sponsoredCount: Int\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n sponsoredCount: $sponsoredCount\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n }\n }\n':
76
- types.ClientManyProductsQueryDocument,
75
+ '\n query ClientManyProductsQueryWithSearchId(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n $sponsoredCount: Int\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n sponsoredCount: $sponsoredCount\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n searchId\n }\n }\n':
76
+ types.ClientManyProductsQueryWithSearchIdDocument,
77
77
  '\n query ClientProductGalleryQuery(\n $first: Int!\n $after: String!\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n ) {\n ...ClientProductGallery\n redirect(term: $term, selectedFacets: $selectedFacets) {\n url\n }\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n ...Filter_facets\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n\n fragment SearchEvent_metadata on SearchMetadata {\n isTermMisspelled\n logicalOperator\n fuzzy\n }\n':
78
78
  types.ClientProductGalleryQueryDocument,
79
79
  '\n query ClientProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ClientProduct\n product(locator: $locator) {\n ...ProductDetailsFragment_product\n }\n }\n':
80
80
  types.ClientProductQueryDocument,
81
+ '\n query ClientManyProductsQuery(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n $sponsoredCount: Int\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n sponsoredCount: $sponsoredCount\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n }\n }\n':
82
+ types.ClientManyProductsQueryDocument,
81
83
  '\n query ClientManyProductsSelectedQuery(\n $productIds: [String!]!\n ) {\n products(productIds: $productIds) {\n ...ProductComparisonFragment_product\n }\n }\n':
82
84
  types.ClientManyProductsSelectedQueryDocument,
83
85
  '\n query ClientProfileQuery($id: String!) {\n profile(id: $id) {\n addresses {\n country\n postalCode\n geoCoordinate\n city\n }\n }\n }\n':
84
86
  types.ClientProfileQueryDocument,
85
- '\n query ClientSearchSuggestionsQuery(\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]\n ) {\n ...ClientSearchSuggestions\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n products {\n ...ProductSummary_product\n }\n }\n products {\n pageInfo {\n totalCount\n }\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n':
87
+ '\n query ClientSearchSuggestionsQuery(\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]\n ) {\n ...ClientSearchSuggestions\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n products {\n ...ProductSummary_product\n }\n }\n products {\n pageInfo {\n totalCount\n }\n }\n metadata {\n ...SearchEvent_metadata\n }\n searchId\n }\n }\n':
86
88
  types.ClientSearchSuggestionsQueryDocument,
87
89
  '\n query ClientTopSearchSuggestionsQuery(\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]\n ) {\n ...ClientTopSearchSuggestions\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n }\n }\n }\n':
88
90
  types.ClientTopSearchSuggestionsQueryDocument,
@@ -278,8 +280,8 @@ export function gql(
278
280
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
279
281
  */
280
282
  export function gql(
281
- source: '\n query ClientManyProductsQuery(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n $sponsoredCount: Int\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n sponsoredCount: $sponsoredCount\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n }\n }\n'
282
- ): typeof import('./graphql').ClientManyProductsQueryDocument
283
+ source: '\n query ClientManyProductsQueryWithSearchId(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n $sponsoredCount: Int\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n sponsoredCount: $sponsoredCount\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n searchId\n }\n }\n'
284
+ ): typeof import('./graphql').ClientManyProductsQueryWithSearchIdDocument
283
285
  /**
284
286
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
285
287
  */
@@ -292,6 +294,12 @@ export function gql(
292
294
  export function gql(
293
295
  source: '\n query ClientProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ClientProduct\n product(locator: $locator) {\n ...ProductDetailsFragment_product\n }\n }\n'
294
296
  ): typeof import('./graphql').ClientProductQueryDocument
297
+ /**
298
+ * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
299
+ */
300
+ export function gql(
301
+ source: '\n query ClientManyProductsQuery(\n $first: Int!\n $after: String\n $sort: StoreSort!\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]!\n $sponsoredCount: Int\n ) {\n ...ClientManyProducts\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n sponsoredCount: $sponsoredCount\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n ...ProductSummary_product\n }\n }\n }\n }\n }\n'
302
+ ): typeof import('./graphql').ClientManyProductsQueryDocument
295
303
  /**
296
304
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
297
305
  */
@@ -308,7 +316,7 @@ export function gql(
308
316
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
309
317
  */
310
318
  export function gql(
311
- source: '\n query ClientSearchSuggestionsQuery(\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]\n ) {\n ...ClientSearchSuggestions\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n products {\n ...ProductSummary_product\n }\n }\n products {\n pageInfo {\n totalCount\n }\n }\n metadata {\n ...SearchEvent_metadata\n }\n }\n }\n'
319
+ source: '\n query ClientSearchSuggestionsQuery(\n $term: String!\n $selectedFacets: [IStoreSelectedFacet!]\n ) {\n ...ClientSearchSuggestions\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n products {\n ...ProductSummary_product\n }\n }\n products {\n pageInfo {\n totalCount\n }\n }\n metadata {\n ...SearchEvent_metadata\n }\n searchId\n }\n }\n'
312
320
  ): typeof import('./graphql').ClientSearchSuggestionsQueryDocument
313
321
  /**
314
322
  * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
@@ -1549,6 +1549,8 @@ export type StoreSearchResult = {
1549
1549
  metadata: Maybe<SearchMetadata>
1550
1550
  /** Search result products. */
1551
1551
  products: StoreProductConnection
1552
+ /** Search result searchId. Unique identifier for the search query can be used to correlate search analytics events. */
1553
+ searchId: Scalars['String']['output']
1552
1554
  /** Search result suggestions. */
1553
1555
  suggestions: StoreSuggestions
1554
1556
  }
@@ -3314,7 +3316,7 @@ export type ClientAllVariantProductsQueryQuery = {
3314
3316
  }
3315
3317
  }
3316
3318
 
3317
- export type ClientManyProductsQueryQueryVariables = Exact<{
3319
+ export type ClientManyProductsQueryWithSearchIdQueryVariables = Exact<{
3318
3320
  first: Scalars['Int']['input']
3319
3321
  after: InputMaybe<Scalars['String']['input']>
3320
3322
  sort: StoreSort
@@ -3323,8 +3325,9 @@ export type ClientManyProductsQueryQueryVariables = Exact<{
3323
3325
  sponsoredCount: InputMaybe<Scalars['Int']['input']>
3324
3326
  }>
3325
3327
 
3326
- export type ClientManyProductsQueryQuery = {
3328
+ export type ClientManyProductsQueryWithSearchIdQuery = {
3327
3329
  search: {
3330
+ searchId: string
3328
3331
  products: {
3329
3332
  pageInfo: { totalCount: number }
3330
3333
  edges: Array<{
@@ -3472,6 +3475,73 @@ export type ClientProductQueryQuery = {
3472
3475
  }
3473
3476
  }
3474
3477
 
3478
+ export type ClientManyProductsQueryQueryVariables = Exact<{
3479
+ first: Scalars['Int']['input']
3480
+ after: InputMaybe<Scalars['String']['input']>
3481
+ sort: StoreSort
3482
+ term: Scalars['String']['input']
3483
+ selectedFacets: Array<IStoreSelectedFacet> | IStoreSelectedFacet
3484
+ sponsoredCount: InputMaybe<Scalars['Int']['input']>
3485
+ }>
3486
+
3487
+ export type ClientManyProductsQueryQuery = {
3488
+ search: {
3489
+ products: {
3490
+ pageInfo: { totalCount: number }
3491
+ edges: Array<{
3492
+ node: {
3493
+ slug: string
3494
+ sku: string
3495
+ name: string
3496
+ gtin: string
3497
+ unitMultiplier: number | null
3498
+ hasSpecifications: boolean | null
3499
+ id: string
3500
+ brand: { name: string; brandName: string }
3501
+ isVariantOf: {
3502
+ productGroupID: string
3503
+ name: string
3504
+ skuVariants: {
3505
+ allVariantsByName: any | null
3506
+ activeVariations: any | null
3507
+ slugsMap: any | null
3508
+ availableVariations: any | null
3509
+ allVariantProducts: Array<{
3510
+ name: string
3511
+ productID: string
3512
+ }> | null
3513
+ } | null
3514
+ }
3515
+ image: Array<{ url: string; alternateName: string }>
3516
+ offers: {
3517
+ lowPrice: number
3518
+ lowPriceWithTaxes: number
3519
+ offers: Array<{
3520
+ availability: string
3521
+ price: number
3522
+ listPrice: number
3523
+ listPriceWithTaxes: number
3524
+ priceWithTaxes: number
3525
+ quantity: number
3526
+ seller: { identifier: string }
3527
+ }>
3528
+ }
3529
+ additionalProperty: Array<{
3530
+ propertyID: string
3531
+ name: string
3532
+ value: any
3533
+ valueReference: any
3534
+ }>
3535
+ advertisement: { adId: string; adResponseId: string } | null
3536
+ deliveryPromiseBadges: Array<{
3537
+ typeName: string | null
3538
+ } | null> | null
3539
+ }
3540
+ }>
3541
+ }
3542
+ }
3543
+ }
3544
+
3475
3545
  export type ClientManyProductsSelectedQueryQueryVariables = Exact<{
3476
3546
  productIds: Array<Scalars['String']['input']> | Scalars['String']['input']
3477
3547
  }>
@@ -3561,6 +3631,7 @@ export type ClientSearchSuggestionsQueryQueryVariables = Exact<{
3561
3631
 
3562
3632
  export type ClientSearchSuggestionsQueryQuery = {
3563
3633
  search: {
3634
+ searchId: string
3564
3635
  suggestions: {
3565
3636
  terms: Array<{ value: string }>
3566
3637
  products: Array<{
@@ -4497,14 +4568,14 @@ export const ClientAllVariantProductsQueryDocument = {
4497
4568
  ClientAllVariantProductsQueryQuery,
4498
4569
  ClientAllVariantProductsQueryQueryVariables
4499
4570
  >
4500
- export const ClientManyProductsQueryDocument = {
4571
+ export const ClientManyProductsQueryWithSearchIdDocument = {
4501
4572
  __meta__: {
4502
- operationName: 'ClientManyProductsQuery',
4503
- operationHash: 'e49027bc29aa10cbf7bbb0ed62239af8de1653f0',
4573
+ operationName: 'ClientManyProductsQueryWithSearchId',
4574
+ operationHash: '23be1e1fcaf0bd2719a9324272c891c922045180',
4504
4575
  },
4505
4576
  } as unknown as TypedDocumentString<
4506
- ClientManyProductsQueryQuery,
4507
- ClientManyProductsQueryQueryVariables
4577
+ ClientManyProductsQueryWithSearchIdQuery,
4578
+ ClientManyProductsQueryWithSearchIdQueryVariables
4508
4579
  >
4509
4580
  export const ClientProductGalleryQueryDocument = {
4510
4581
  __meta__: {
@@ -4524,6 +4595,15 @@ export const ClientProductQueryDocument = {
4524
4595
  ClientProductQueryQuery,
4525
4596
  ClientProductQueryQueryVariables
4526
4597
  >
4598
+ export const ClientManyProductsQueryDocument = {
4599
+ __meta__: {
4600
+ operationName: 'ClientManyProductsQuery',
4601
+ operationHash: 'e49027bc29aa10cbf7bbb0ed62239af8de1653f0',
4602
+ },
4603
+ } as unknown as TypedDocumentString<
4604
+ ClientManyProductsQueryQuery,
4605
+ ClientManyProductsQueryQueryVariables
4606
+ >
4527
4607
  export const ClientManyProductsSelectedQueryDocument = {
4528
4608
  __meta__: {
4529
4609
  operationName: 'ClientManyProductsSelectedQuery',
@@ -4545,7 +4625,7 @@ export const ClientProfileQueryDocument = {
4545
4625
  export const ClientSearchSuggestionsQueryDocument = {
4546
4626
  __meta__: {
4547
4627
  operationName: 'ClientSearchSuggestionsQuery',
4548
- operationHash: 'bbaa2ed75c4fb04842189e8d53a1d65481154e2b',
4628
+ operationHash: '1517112c3f6aa9e5031ed8cbad61d97973e0a5b7',
4549
4629
  },
4550
4630
  } as unknown as TypedDocumentString<
4551
4631
  ClientSearchSuggestionsQueryQuery,
@@ -15,12 +15,13 @@
15
15
  "feb7005103a859e2bc8cf2360d568806fd88deba": "mutation SubscribeToNewsletter($data: IPersonNewsletter!) { subscribeToNewsletter(data: $data) { id } }",
16
16
  "dc912e7272e3d9f5ced206837df87f544d39d0a5": "query ClientProductCountQuery($term: String) { productCount(term: $term) { total } }",
17
17
  "4039e05f01a2fe449e20e8b82170d0ba94b1fbe9": "fragment ProductSKUMatrixSidebarFragment_product on StoreProduct { isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { additionalProperty { name propertyID value valueReference } image { alternateName url } name offers { highPrice lowPrice lowPriceWithTaxes offerCount offers { availability itemCondition listPrice listPriceWithTaxes price priceCurrency priceValidUntil priceWithTaxes quantity sellingPrice } priceCurrency } sku } availableVariations slugsMap } } id: productID } query ClientAllVariantProductsQuery($locator: [IStoreSelectedFacet!]!) { product(locator: $locator) { ...ProductSKUMatrixSidebarFragment_product } }",
18
- "e49027bc29aa10cbf7bbb0ed62239af8de1653f0": "fragment ClientManyProducts on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { products { pageInfo { totalCount } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } deliveryPromiseBadges { typeName } gtin hasSpecifications image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier unitMultiplier } query ClientManyProductsQuery($after: String, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $sponsoredCount: Int, $term: String!) { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { products { edges { node { ...ProductSummary_product } } pageInfo { totalCount } } } ...ClientManyProducts }",
18
+ "23be1e1fcaf0bd2719a9324272c891c922045180": "fragment ClientManyProducts on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { products { pageInfo { totalCount } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } deliveryPromiseBadges { typeName } gtin hasSpecifications image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier unitMultiplier } query ClientManyProductsQueryWithSearchId($after: String, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $sponsoredCount: Int, $term: String!) { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { products { edges { node { ...ProductSummary_product } } pageInfo { totalCount } } searchId } ...ClientManyProducts }",
19
19
  "bfc40da32b60f9404a4adb96b0856e3fbb04b076": "fragment ClientProductGallery on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets ) { products { pageInfo { totalCount } } } } fragment Filter_facets on StoreFacet { ... on StoreFacetBoolean { __typename key label values { label quantity selected value } } ... on StoreFacetRange { __typename key label max { absolute selected } min { absolute selected } } } fragment SearchEvent_metadata on SearchMetadata { fuzzy isTermMisspelled logicalOperator } query ClientProductGalleryQuery($after: String!, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $term: String!) { redirect(term: $term, selectedFacets: $selectedFacets) { url } search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets ) { facets { ...Filter_facets } metadata { ...SearchEvent_metadata } products { pageInfo { totalCount } } } ...ClientProductGallery }",
20
20
  "47aa22eb750cb2c529e5eeafb921bfeadb67db71": "fragment CartProductItem on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations availableVariations slugsMap } } name sku unitMultiplier } fragment ClientProduct on Query { product(locator: $locator) { id: productID } } fragment ProductDetailsFragment_product on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } description gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes seller { identifier } } } id: productID sku unitMultiplier ...CartProductItem } query ClientProductQuery($locator: [IStoreSelectedFacet!]!) { product(locator: $locator) { ...ProductDetailsFragment_product } ...ClientProduct }",
21
+ "e49027bc29aa10cbf7bbb0ed62239af8de1653f0": "fragment ClientManyProducts on Query { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { products { pageInfo { totalCount } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } deliveryPromiseBadges { typeName } gtin hasSpecifications image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier unitMultiplier } query ClientManyProductsQuery($after: String, $first: Int!, $selectedFacets: [IStoreSelectedFacet!]!, $sort: StoreSort!, $sponsoredCount: Int, $term: String!) { search( first: $first after: $after sort: $sort term: $term selectedFacets: $selectedFacets sponsoredCount: $sponsoredCount ) { products { edges { node { ...ProductSummary_product } } pageInfo { totalCount } } } ...ClientManyProducts }",
21
22
  "b668777678c137b8c7004297df4d8b8f2b29ee06": "fragment ProductComparisonFragment_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { name } description gtin hasSpecifications image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku skuSpecifications { field { id name originalName } values { fieldId id name originalName } } slug specificationGroups { name originalName specifications { name originalName values } } unitMultiplier } query ClientManyProductsSelectedQuery($productIds: [String!]!) { products(productIds: $productIds) { ...ProductComparisonFragment_product } }",
22
23
  "34ea14c0d4a57ddf9bc11e4be0cd2b5a6506d3d4": "query ClientProfileQuery($id: String!) { profile(id: $id) { addresses { city country geoCoordinate postalCode } } }",
23
- "bbaa2ed75c4fb04842189e8d53a1d65481154e2b": "fragment ClientSearchSuggestions on Query { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } deliveryPromiseBadges { typeName } gtin hasSpecifications image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier unitMultiplier } fragment SearchEvent_metadata on SearchMetadata { fuzzy isTermMisspelled logicalOperator } query ClientSearchSuggestionsQuery($selectedFacets: [IStoreSelectedFacet!], $term: String!) { search(first: 5, term: $term, selectedFacets: $selectedFacets) { metadata { ...SearchEvent_metadata } products { pageInfo { totalCount } } suggestions { products { ...ProductSummary_product } terms { value } } } ...ClientSearchSuggestions }",
24
+ "1517112c3f6aa9e5031ed8cbad61d97973e0a5b7": "fragment ClientSearchSuggestions on Query { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } } fragment ProductSummary_product on StoreProduct { additionalProperty { name propertyID value valueReference } advertisement { adId adResponseId } brand { brandName: name } brand { name } deliveryPromiseBadges { typeName } gtin hasSpecifications image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantsByName availableVariations slugsMap } } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceWithTaxes quantity seller { identifier } } } id: productID sku slug unitMultiplier unitMultiplier } fragment SearchEvent_metadata on SearchMetadata { fuzzy isTermMisspelled logicalOperator } query ClientSearchSuggestionsQuery($selectedFacets: [IStoreSelectedFacet!], $term: String!) { search(first: 5, term: $term, selectedFacets: $selectedFacets) { metadata { ...SearchEvent_metadata } products { pageInfo { totalCount } } searchId suggestions { products { ...ProductSummary_product } terms { value } } } ...ClientSearchSuggestions }",
24
25
  "e2385b0f11726d0068f96548f57a8dd441c064e3": "fragment ClientTopSearchSuggestions on Query { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } } query ClientTopSearchSuggestionsQuery($selectedFacets: [IStoreSelectedFacet!], $term: String!) { search(first: 5, term: $term, selectedFacets: $selectedFacets) { suggestions { terms { value } } } ...ClientTopSearchSuggestions }",
25
26
  "8c3a5999496e227f167e9dc79697e6c478d48a9e": "mutation ValidateSession($search: String!, $session: IStoreSession!) { validateSession(session: $session, search: $search) { addressType b2b { contractName customerId firstName isRepresentative lastName organizationManager savedPostalCode unitId unitName userEmail userName } channel city country currency { code symbol } deliveryMode { deliveryChannel deliveryMethod deliveryWindow { endDate startDate } } geoCoordinates { latitude longitude } locale marketingData { utmCampaign utmMedium utmSource utmiCampaign utmiPage utmiPart } person { email familyName givenName id } postalCode refreshAfter } }",
26
27
  "c35bad22f67f3eb34fea52bb49efa6b1da6b728d": "fragment ClientShippingSimulation on Query { shipping(items: $items, postalCode: $postalCode, country: $country) { address { city } } } query ClientShippingSimulationQuery($country: String!, $items: [IShippingItem!]!, $postalCode: String!) { shipping(items: $items, postalCode: $postalCode, country: $country) { address { city neighborhood state } logisticsInfo { slas { availableDeliveryWindows { endDateUtc listPrice price startDateUtc } carrier deliveryChannel localizedEstimates price shippingEstimate } } } ...ClientShippingSimulation }",
@@ -933,6 +933,8 @@ type StoreSearchResult {
933
933
  suggestions: StoreSuggestions!
934
934
  """Search result metadata. Additional data can be used to send analytics events."""
935
935
  metadata: SearchMetadata
936
+ """Search result searchId. Unique identifier for the search query can be used to correlate search analytics events."""
937
+ searchId: String!
936
938
  }
937
939
 
938
940
  input IGeoCoordinates {
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.98.0-dev.3](https://github.com/vtex/faststore/compare/v3.98.0-dev.2...v3.98.0-dev.3) (2026-03-12)
7
+
8
+ ### Features
9
+
10
+ - Add ActivityFlow data parameters with search-related information ([#3105](https://github.com/vtex/faststore/issues/3105)) ([8f69ff8](https://github.com/vtex/faststore/commit/8f69ff855c31abedba66071132240c53a93ab56d))
11
+
6
12
  # [3.98.0-dev.2](https://github.com/vtex/faststore/compare/v3.98.0-dev.1...v3.98.0-dev.2) (2026-03-03)
7
13
 
8
14
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/core",
3
- "version": "3.98.0-dev.2",
3
+ "version": "3.98.0-dev.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -51,11 +51,11 @@
51
51
  "@envelop/graphql-jit": "^8.0.3",
52
52
  "@envelop/parser-cache": "^6.0.2",
53
53
  "@envelop/validation-cache": "^6.0.2",
54
- "@faststore/api": "3.98.0-dev.2",
54
+ "@faststore/api": "3.98.0-dev.3",
55
55
  "@faststore/graphql-utils": "^3.98.0-dev.1",
56
56
  "@faststore/lighthouse": "3.98.0-dev.1",
57
57
  "@faststore/sdk": "3.98.0-dev.1",
58
- "@faststore/ui": "3.98.0-dev.1",
58
+ "@faststore/ui": "3.98.0-dev.3",
59
59
  "@graphql-codegen/cli": "5.0.2",
60
60
  "@graphql-codegen/client-preset": "4.2.6",
61
61
  "@graphql-codegen/typescript": "4.0.7",
@@ -123,5 +123,5 @@
123
123
  "ts-jest": "29.1.1",
124
124
  "typescript": "5.3.2"
125
125
  },
126
- "gitHead": "9438b20a0e937561672271b92b69a5c2b20a8cb1"
126
+ "gitHead": "c6e0f65660673a92f9de733b7502551ef755e86c"
127
127
  }
@@ -48,6 +48,22 @@ interface Props {
48
48
  * Title for the `ProductGrid` component that will be send to GA events.
49
49
  */
50
50
  title?: string
51
+ searchId?: string
52
+ /**
53
+ * Function that returns optional external porps for each product summary.
54
+ * The returned key/value pairs will be spread onto the corresponding section element.
55
+ *
56
+ * @example
57
+ * buildExtraProductProps={(product, index, searchId) => ({
58
+ * 'data-af-category': product.category || 'unknown',
59
+ * 'data-af-index': String(index),
60
+ * })}
61
+ */
62
+ buildExtraProductProps?: (
63
+ product: Record<string, any>,
64
+ index: number,
65
+ searchId: string
66
+ ) => Record<string, string | number | boolean>
51
67
  }
52
68
 
53
69
  function ProductGrid({
@@ -64,6 +80,8 @@ function ProductGrid({
64
80
  shouldShowComparison,
65
81
  compareLabel,
66
82
  title,
83
+ searchId,
84
+ buildExtraProductProps = () => ({}),
67
85
  }: Props) {
68
86
  const { isMobile } = useScreenResize()
69
87
  const { __experimentalProductCard: ProductCard } =
@@ -77,7 +95,11 @@ function ProductGrid({
77
95
  aspectRatio={aspectRatio}
78
96
  loading={products.length === 0}
79
97
  >
80
- <UIProductGrid>
98
+ <UIProductGrid
99
+ data-af-element={searchId && 'search-result'}
100
+ data-af-onimpression={!!searchId}
101
+ data-af-search-id={searchId}
102
+ >
81
103
  {isGridWithViewportObserver ? (
82
104
  // In mobile, the ProductGrid initially renders the first 2 items, the rest of the items are rendered when they come into the viewport.
83
105
  <>
@@ -108,6 +130,7 @@ function ProductGrid({
108
130
  index={pageSize * page + idx + 1}
109
131
  taxesConfiguration={taxesConfiguration}
110
132
  sponsoredLabel={sponsoredLabel}
133
+ {...buildExtraProductProps(product, idx, searchId)}
111
134
  />
112
135
  </ProductSentinel>
113
136
  </UIProductGridItem>
@@ -140,6 +163,7 @@ function ProductGrid({
140
163
  index={pageSize * page + idx + 1}
141
164
  taxesConfiguration={taxesConfiguration}
142
165
  sponsoredLabel={sponsoredLabel}
166
+ {...buildExtraProductProps(product, idx, searchId)}
143
167
  />
144
168
  </ProductSentinel>
145
169
  </UIProductGridItem>
@@ -175,6 +199,7 @@ function ProductGrid({
175
199
  index={pageSize * page + idx + 1}
176
200
  taxesConfiguration={taxesConfiguration}
177
201
  sponsoredLabel={sponsoredLabel}
202
+ {...buildExtraProductProps(product, idx, searchId)}
178
203
  />
179
204
  </ProductSentinel>
180
205
  </UIProductGridItem>
@@ -48,7 +48,7 @@ function SearchDropdown({
48
48
  ...otherProps
49
49
  }: SearchDropdownProps) {
50
50
  const {
51
- values: { onSearchSelection, products, term, terms },
51
+ values: { onSearchSelection, products, term, terms, searchId },
52
52
  } = useSearch()
53
53
 
54
54
  return (
@@ -92,7 +92,11 @@ function SearchDropdown({
92
92
  />
93
93
  ))}
94
94
  </UISearchAutoComplete>
95
- <SearchProducts>
95
+ <SearchProducts
96
+ data-af-element={searchId && 'search-autocomplete'}
97
+ data-af-onimpression={!!searchId}
98
+ data-af-search-id={searchId}
99
+ >
96
100
  {products.map((product, index) => {
97
101
  const productParsed = product as ProductSummary_ProductFragment
98
102
  return (
@@ -104,6 +108,11 @@ function SearchDropdown({
104
108
  onChangeCustomSearchDropdownVisible={
105
109
  onChangeCustomSearchDropdownVisible
106
110
  }
111
+ data-af-element={searchId && 'search-autocomplete'}
112
+ data-af-onclick={!!(searchId && productParsed.id)}
113
+ data-af-search-id={searchId}
114
+ data-af-product-position={searchId && index + 1} // Product position in Search Analytics starts with 1
115
+ data-af-product-id={searchId && productParsed.id}
107
116
  />
108
117
  )
109
118
  })}
@@ -122,6 +122,7 @@ const SearchInput = forwardRef<SearchInputRef, SearchInputProps>(
122
122
  MAX_SUGGESTIONS
123
123
  )
124
124
  const isLoading = !error && !data
125
+ const searchId = data?.search.searchId
125
126
 
126
127
  const buttonProps = {
127
128
  onClick: onSearchClick,
@@ -147,6 +148,7 @@ const SearchInput = forwardRef<SearchInputRef, SearchInputProps>(
147
148
  terms={terms}
148
149
  products={products}
149
150
  isLoading={isLoading}
151
+ searchId={searchId}
150
152
  >
151
153
  <UISearchInputField
152
154
  ref={ref}
@@ -73,7 +73,7 @@ export default function ProductListing({
73
73
  itemsPerPage,
74
74
  })
75
75
 
76
- const initialPages = { search: server?.search }
76
+ const initialPages = { search: { ...server?.search, searchId: '' } }
77
77
  const { pages, useGalleryPage } = useCreateUseGalleryPage({
78
78
  initialPages,
79
79
  serverManyProductsVariables,
@@ -18,6 +18,20 @@ interface Props {
18
18
  compareLabel?: string
19
19
  }
20
20
 
21
+ function buildExtraProductProps(
22
+ product: Record<string, string>,
23
+ index: number,
24
+ searchId: string
25
+ ) {
26
+ return {
27
+ 'data-af-element': 'search-result',
28
+ 'data-af-onclick': product && !!product.productId,
29
+ 'data-af-search-id': searchId,
30
+ 'data-af-product-position': Number(index ?? 0) + 1, // Product position in Search Analytics starts with 1
31
+ 'data-af-product-id': product && product.productId,
32
+ }
33
+ }
34
+
21
35
  function ProductGalleryPage({
22
36
  page,
23
37
  title,
@@ -30,6 +44,7 @@ function ProductGalleryPage({
30
44
  const { data } = useGalleryPage(page)
31
45
 
32
46
  const products = data?.search?.products?.edges ?? []
47
+ const searchId = data?.search?.searchId
33
48
 
34
49
  return (
35
50
  <Sentinel
@@ -47,6 +62,8 @@ function ProductGalleryPage({
47
62
  productCard={productCard}
48
63
  firstPage={firstPage}
49
64
  title={title}
65
+ searchId={searchId}
66
+ buildExtraProductProps={searchId && buildExtraProductProps}
50
67
  />
51
68
  </Sentinel>
52
69
  )
@@ -1,8 +1,8 @@
1
1
  import { useSearch } from '@faststore/sdk'
2
2
  import { gql } from '@generated'
3
3
  import type {
4
- ClientManyProductsQueryQuery,
5
- ClientManyProductsQueryQueryVariables,
4
+ ClientManyProductsQueryWithSearchIdQuery,
5
+ ClientManyProductsQueryWithSearchIdQueryVariables,
6
6
  } from '@generated/graphql'
7
7
  import deepEquals from 'fast-deep-equal'
8
8
  import {
@@ -34,7 +34,7 @@ export const useGalleryPage = (page: number) => {
34
34
  }
35
35
 
36
36
  export const query = gql(`
37
- query ClientManyProductsQuery(
37
+ query ClientManyProductsQueryWithSearchId(
38
38
  $first: Int!
39
39
  $after: String
40
40
  $sort: StoreSort!
@@ -61,6 +61,7 @@ export const query = gql(`
61
61
  }
62
62
  }
63
63
  }
64
+ searchId
64
65
  }
65
66
  }
66
67
  `)
@@ -68,8 +69,8 @@ export const query = gql(`
68
69
  const getKey = (object: any) => JSON.stringify(object)
69
70
 
70
71
  interface UseCreateUseGalleryPageProps {
71
- initialPages: ClientManyProductsQueryQuery
72
- serverManyProductsVariables: ClientManyProductsQueryQueryVariables
72
+ initialPages: ClientManyProductsQueryWithSearchIdQuery
73
+ serverManyProductsVariables: ClientManyProductsQueryWithSearchIdQueryVariables
73
74
  }
74
75
 
75
76
  /**
@@ -84,9 +85,10 @@ export const useCreateUseGalleryPage = (
84
85
  : []
85
86
 
86
87
  const [pages, setPages] =
87
- useState<ClientManyProductsQueryQuery[]>(initialPages)
88
+ useState<ClientManyProductsQueryWithSearchIdQuery[]>(initialPages)
88
89
  // We create pagesRef as a mirror of the pages state so we don't have to add pages as a dependency of the useGalleryPage hook
89
- const pagesRef = useRef<ClientManyProductsQueryQuery[]>(initialPages)
90
+ const pagesRef =
91
+ useRef<ClientManyProductsQueryWithSearchIdQuery[]>(initialPages)
90
92
  const pagesCache = useRef<string[]>(initialVariables)
91
93
 
92
94
  const useGalleryPage = useCallback(function useGalleryPage(page: number) {
@@ -116,8 +118,8 @@ export const useCreateUseGalleryPage = (
116
118
  const shouldFetch = !hasSameVariables || shouldFetchFirstPage
117
119
 
118
120
  const { data } = useQuery<
119
- ClientManyProductsQueryQuery,
120
- ClientManyProductsQueryQueryVariables
121
+ ClientManyProductsQueryWithSearchIdQuery,
122
+ ClientManyProductsQueryWithSearchIdQueryVariables
121
123
  >(query, localizedVariables, {
122
124
  fallbackData: null,
123
125
  suspense: true,
@@ -34,6 +34,7 @@ const query = gql(`
34
34
  metadata {
35
35
  ...SearchEvent_metadata
36
36
  }
37
+ searchId
37
38
  }
38
39
  }
39
40
  `)