@replohq/sdk 1.21.1 → 2.0.0

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 (119) hide show
  1. package/_vendor/replo-utils/lib/json.mjs +4 -5
  2. package/_vendor/replo-utils/lib/misc.mjs +4 -3
  3. package/_vendor/replo-utils/lib/object.d.ts +16 -1
  4. package/_vendor/replo-utils/lib/object.mjs +3 -4
  5. package/_vendor/schemas/contentEntry.mjs +3 -3
  6. package/_vendor/schemas/contentManifest.mjs +6 -6
  7. package/_vendor/schemas/errors.d.ts +3 -43
  8. package/_vendor/schemas/{money.d.ts → moneyFormat.d.ts} +1 -8
  9. package/_vendor/schemas/{money.mjs → moneyFormat.mjs} +5 -16
  10. package/_vendor/schemas/reploError.d.ts +43 -0
  11. package/_vendor/schemas/routing/locale.mjs +6 -4
  12. package/_vendor/schemas/routing/rules.mjs +6 -4
  13. package/analytics/analytics-sink.d.ts +126 -14
  14. package/analytics/combine-sinks.js +36 -13
  15. package/analytics/hooks/use-product-viewed-analytics.d.ts +1 -17
  16. package/analytics/hooks/use-product-viewed-analytics.js +5 -14
  17. package/analytics/legacy-checkout.d.ts +2 -0
  18. package/analytics/legacy-checkout.js +26 -0
  19. package/analytics/sinks/converge-event-mapper.d.ts +10 -11
  20. package/analytics/sinks/converge-event-mapper.js +50 -133
  21. package/analytics/sinks/converge-sink.d.ts +8 -7
  22. package/analytics/sinks/converge-sink.js +21 -3
  23. package/analytics/sinks/elevar-sink.d.ts +9 -7
  24. package/analytics/sinks/elevar-sink.js +37 -128
  25. package/analytics/sinks/ga4-sink.d.ts +9 -8
  26. package/analytics/sinks/ga4-sink.js +9 -8
  27. package/analytics/sinks/intelligems-sink.d.ts +9 -8
  28. package/analytics/sinks/intelligems-sink.js +3 -1
  29. package/analytics/sinks/meta-sink.d.ts +5 -4
  30. package/analytics/sinks/meta-sink.js +7 -3
  31. package/analytics/sinks/northbeam-sink.d.ts +1 -0
  32. package/analytics/sinks/northbeam-sink.js +2 -0
  33. package/analytics/sinks/pinterest-sink.d.ts +7 -6
  34. package/analytics/sinks/pinterest-sink.js +14 -20
  35. package/analytics/sinks/reddit-sink.d.ts +8 -7
  36. package/analytics/sinks/reddit-sink.js +13 -20
  37. package/analytics/sinks/replo-sink.d.ts +21 -9
  38. package/analytics/sinks/replo-sink.js +37 -39
  39. package/analytics/sinks/snapchat-sink.d.ts +6 -5
  40. package/analytics/sinks/snapchat-sink.js +8 -8
  41. package/analytics/sinks/tiktok-sink.d.ts +8 -7
  42. package/analytics/sinks/tiktok-sink.js +10 -15
  43. package/analytics/sinks/window-sink.d.ts +11 -9
  44. package/analytics/sinks/window-sink.js +5 -1
  45. package/analytics/sinks/x-sink.d.ts +5 -4
  46. package/analytics/sinks/x-sink.js +19 -50
  47. package/analytics/test-fixtures.d.ts +5 -0
  48. package/analytics/test-fixtures.js +18 -0
  49. package/analytics/utils/analytics-products.d.ts +0 -30
  50. package/analytics/utils/analytics-products.js +1 -51
  51. package/analytics/utils/collection-analytics.d.ts +2 -15
  52. package/analytics/utils/collection-analytics.js +14 -18
  53. package/analytics/utils/product-analytics.d.ts +23 -0
  54. package/analytics/utils/product-analytics.js +21 -0
  55. package/cart/hooks/use-add-to-cart.js +1 -1
  56. package/cart/utils/cart-analytics.d.ts +3 -23
  57. package/cart/utils/cart-analytics.js +1 -1
  58. package/cart/utils/cart-utils.js +1 -1
  59. package/cart/utils/variant-to-cart-line.js +1 -1
  60. package/chunk-CKRRL66R.mjs +28 -0
  61. package/{chunk-VVB7BEDE.mjs → chunk-O4QBR4QC.mjs} +9 -4
  62. package/{chunk-EUIVDITZ.mjs → chunk-OPKMOW43.mjs} +1 -1
  63. package/{chunk-C37TXOGI.mjs → chunk-PSYP2DYM.mjs} +1 -1
  64. package/{chunk-ACQS4AG5.mjs → chunk-TTEBDCWT.mjs} +272 -109
  65. package/{chunk-HFKL4ZR5.mjs → chunk-XGXJOHUY.mjs} +2 -1
  66. package/{chunk-AQG3256R.mjs → chunk-XSMYSAKY.mjs} +0 -26
  67. package/{chunk-SSBIMQES.mjs → chunk-XWWFRIXV.mjs} +36 -99
  68. package/chunk-ZPDXVFCR.mjs +66 -0
  69. package/hooks/use-formatted-price.js +1 -1
  70. package/lib/buildMetadata.js +3 -3
  71. package/loaders/collection-loader.js +8 -6
  72. package/loaders/collection-products-loader.js +8 -6
  73. package/loaders/contentful-entries-loader.js +5 -3
  74. package/loaders/contentful-entry-loader.js +5 -3
  75. package/loaders/integration-loader-schemas.d.ts +260 -0
  76. package/loaders/integration-loader-schemas.js +55 -0
  77. package/loaders/invoke-loader.d.ts +5 -0
  78. package/loaders/invoke-loader.js +1 -1
  79. package/loaders/judgeme-review-aggregate-loader.d.ts +1 -1
  80. package/loaders/judgeme-review-aggregate-loader.js +10 -6
  81. package/loaders/judgeme-reviews-loader.d.ts +1 -1
  82. package/loaders/judgeme-reviews-loader.js +5 -3
  83. package/loaders/kaching-bundles-loader.js +5 -3
  84. package/loaders/levanta-product-loader.js +8 -6
  85. package/loaders/loox-review-aggregate-loader.d.ts +1 -1
  86. package/loaders/loox-review-aggregate-loader.js +10 -6
  87. package/loaders/loox-reviews-loader.d.ts +1 -1
  88. package/loaders/loox-reviews-loader.js +8 -6
  89. package/loaders/metaobject-loader.js +5 -3
  90. package/loaders/metaobjects-loader.js +5 -3
  91. package/loaders/okendo-review-aggregate-loader.d.ts +2 -7
  92. package/loaders/okendo-review-aggregate-loader.js +8 -12
  93. package/loaders/okendo-reviews-loader.d.ts +2 -42
  94. package/loaders/okendo-reviews-loader.js +5 -8
  95. package/loaders/product-loader.js +5 -3
  96. package/loaders/rebuy-recommendations-loader.d.ts +2 -167
  97. package/loaders/rebuy-recommendations-loader.js +8 -10
  98. package/loaders/reviews-io-review-aggregate-loader.d.ts +1 -1
  99. package/loaders/reviews-io-review-aggregate-loader.js +5 -3
  100. package/loaders/reviews-io-reviews-loader.d.ts +1 -1
  101. package/loaders/reviews-io-reviews-loader.js +7 -3
  102. package/loaders/shopify-integration-details-loader.js +10 -6
  103. package/loaders/smile-earning-rules-loader.d.ts +2 -8
  104. package/loaders/smile-earning-rules-loader.js +8 -16
  105. package/loaders/smile-rewards-loader.d.ts +2 -8
  106. package/loaders/smile-rewards-loader.js +8 -16
  107. package/loaders/smile-vip-tiers-loader.d.ts +2 -7
  108. package/loaders/smile-vip-tiers-loader.js +8 -15
  109. package/loaders/statsig-experiment-loader.js +5 -3
  110. package/loaders/yotpo-review-aggregate-loader.d.ts +1 -1
  111. package/loaders/yotpo-review-aggregate-loader.js +10 -6
  112. package/loaders/yotpo-reviews-loader.d.ts +1 -1
  113. package/loaders/yotpo-reviews-loader.js +5 -3
  114. package/money.d.ts +1 -1
  115. package/money.js +1 -1
  116. package/next/config.js +4 -0
  117. package/next/image-loader.js +3 -3
  118. package/package.json +8 -4
  119. package/chunk-CQYCPDPI.mjs +0 -166
@@ -1,153 +1,59 @@
1
1
  import { filterUndefined } from "../../_vendor/replo-utils/lib/object.mjs";
2
- import * as z from "zod";
3
- const analyticsRecordSchema = z.record(z.string(), z.unknown());
4
- const nonEmptyStringSchema = z.union([
5
- z.string().min(1),
6
- z.number().finite().transform(String)
7
- ]);
8
- const finiteNumberSchema = z.union([
9
- z.number().finite(),
10
- z.string().trim().min(1).transform(Number).pipe(z.number().finite())
11
- ]);
12
- const couponSchema = z.union([z.string(), z.array(z.string())]);
13
- function parseRecord(value) {
14
- const result = analyticsRecordSchema.safeParse(value);
15
- return result.success ? result.data : null;
16
- }
17
- function firstValue(record, keys) {
18
- for (const key of keys) {
19
- const value = record[key];
20
- if (value !== null && value !== void 0) {
21
- return value;
22
- }
23
- }
24
- return void 0;
25
- }
26
- function parseString(value) {
27
- const result = nonEmptyStringSchema.safeParse(value);
28
- return result.success ? result.data : void 0;
29
- }
30
- function numberValue(value) {
31
- const result = finiteNumberSchema.safeParse(value);
32
- return result.success ? result.data : void 0;
33
- }
34
- function stringFrom(record, keys) {
35
- return parseString(firstValue(record, keys));
36
- }
37
- function numberFrom(record, keys) {
38
- return numberValue(firstValue(record, keys));
39
- }
40
- function moneyFrom(value) {
41
- const record = parseRecord(value);
42
- if (!record) {
2
+ function mapProduct(line, currency = line.currency) {
3
+ if (!line.productTitle || line.price === void 0 || !currency) {
43
4
  return null;
44
5
  }
45
6
  return {
46
- amount: numberFrom(record, ["amount"]),
47
- currency: stringFrom(record, ["currencyCode", "currency"])
48
- };
49
- }
50
- function optionalProductProperties({
51
- source,
52
- variant,
53
- product
54
- }) {
55
- return {
56
- variant_id: stringFrom(source, ["variant_id", "variantId"]) ?? stringFrom(variant, ["id"]),
57
- sku: stringFrom(source, ["sku", "variantSku"]) ?? stringFrom(variant, ["sku"]),
58
- variant_name: stringFrom(source, ["variant_name", "variantTitle"]) ?? stringFrom(variant, ["title"]),
59
- vendor: stringFrom(source, ["vendor", "productVendor"]) ?? stringFrom(product, ["vendor"]),
60
- url: stringFrom(source, ["url", "productUrl"]) ?? stringFrom(product, ["url"]),
61
- image_url: stringFrom(source, ["image_url", "imageUrl", "productImageUrl"]) ?? stringFrom(product, ["imageUrl", "image_url"])
62
- };
63
- }
64
- function mapProduct(value, defaults = {}) {
65
- const source = parseRecord(value);
66
- if (!source) {
67
- return null;
68
- }
69
- const variant = parseRecord(source.variant) ?? {};
70
- const product = parseRecord(variant.product) ?? parseRecord(source.product) ?? {};
71
- const variantPrice = moneyFrom(variant.price);
72
- const sourcePrice = moneyFrom(source.price);
73
- const productId = stringFrom(source, ["product_id", "productId"]) ?? stringFrom(product, ["id"]);
74
- const name = stringFrom(source, ["name", "productTitle", "title"]) ?? stringFrom(product, ["title", "name"]);
75
- const price = numberFrom(source, ["price"]) ?? sourcePrice?.amount ?? variantPrice?.amount;
76
- const currency = stringFrom(source, ["currency", "currencyCode"]) ?? sourcePrice?.currency ?? variantPrice?.currency ?? defaults.currency;
77
- if (!productId || !name || price === void 0 || !currency) {
78
- return null;
79
- }
80
- const quantity = numberFrom(source, ["quantity"]) ?? defaults.quantity;
81
- const mapped = {
82
- product_id: productId,
83
- name,
84
- price,
7
+ product_id: line.productId,
8
+ name: line.productTitle,
9
+ price: line.price,
85
10
  currency,
86
- ...filterUndefined(optionalProductProperties({ source, variant, product })),
87
- ...quantity === void 0 ? {} : { quantity }
11
+ ...filterUndefined({
12
+ variant_id: line.variantId || void 0,
13
+ sku: line.variantSku || void 0,
14
+ variant_name: line.variantTitle || void 0
15
+ })
88
16
  };
89
- return mapped;
90
- }
91
- function listFrom(record, keys) {
92
- const value = firstValue(record, keys);
93
- return Array.isArray(value) ? value : [];
94
17
  }
95
- function couponFrom(record) {
96
- const result = couponSchema.safeParse(
97
- firstValue(record, ["coupon", "discountCode"])
98
- );
99
- return result.success ? result.data : void 0;
18
+ function mapCartItems(lines, currency) {
19
+ const items = lines.flatMap((line) => {
20
+ const product = mapProduct(line, line.currency ?? currency);
21
+ return product ? [{ ...product, quantity: line.quantity }] : [];
22
+ });
23
+ return items.length > 0 ? items : void 0;
100
24
  }
101
25
  function mapConvergeProduct(data) {
102
- const product = mapProduct(data);
103
- if (!product) {
104
- return null;
105
- }
106
- const { quantity: _quantity, ...properties } = product;
107
- return properties;
26
+ return mapProduct(data);
108
27
  }
109
28
  function mapConvergeCartItem(data) {
110
- const product = mapProduct(data, { quantity: 1 });
111
- if (!product || product.quantity === void 0) {
112
- return null;
113
- }
114
- return { ...product, quantity: product.quantity };
29
+ const product = mapProduct(data);
30
+ return product ? { ...product, quantity: data.quantity } : null;
115
31
  }
116
32
  function mapConvergeCollection(data) {
117
- const id = stringFrom(data, ["id", "collectionId"]);
118
- const name = stringFrom(data, ["name", "collectionTitle"]);
119
- if (!id || !name) {
33
+ if (!data.collectionTitle) {
120
34
  return null;
121
35
  }
122
- const items = listFrom(data, ["items", "products"]).map((item) => mapProduct(item)).filter((item) => item !== null).map(({ quantity: _quantity, ...item }) => item);
36
+ const items = data.products.flatMap((line) => mapProduct(line) ?? []);
123
37
  return {
124
- id,
125
- name,
126
- ...filterUndefined({
127
- description: stringFrom(data, ["description", "collectionDescription"]),
128
- items: items.length > 0 ? items : void 0
129
- })
38
+ id: data.collectionId,
39
+ name: data.collectionTitle,
40
+ ...items.length > 0 ? { items } : {}
130
41
  };
131
42
  }
132
- function mapConvergeCart(data) {
133
- const totalPriceMoney = moneyFrom(firstValue(data, ["totalPrice"]));
134
- const subtotalMoney = moneyFrom(firstValue(data, ["subtotalPrice"]));
135
- const currency = stringFrom(data, ["currency", "currencyCode"]) ?? totalPriceMoney?.currency ?? subtotalMoney?.currency;
136
- const totalPrice = numberFrom(data, ["total_price", "totalAmount", "subtotal"]) ?? totalPriceMoney?.amount ?? subtotalMoney?.amount;
137
- if (totalPrice === void 0 || !currency) {
43
+ function mapConvergeCart({
44
+ totalPrice,
45
+ currency,
46
+ lineItems
47
+ }) {
48
+ if (!currency) {
138
49
  return null;
139
50
  }
140
- const items = listFrom(data, ["items", "lineItems"]).map((item) => mapProduct(item, { currency, quantity: 1 })).filter((item) => item?.quantity !== void 0);
141
51
  return {
142
52
  total_price: totalPrice,
143
- total_tax: numberFrom(data, ["total_tax", "totalTax"]) ?? 0,
144
- total_shipping: numberFrom(data, ["total_shipping", "totalShipping"]) ?? 0,
53
+ total_tax: 0,
54
+ total_shipping: 0,
145
55
  currency,
146
- ...filterUndefined({
147
- total_discount: numberFrom(data, ["total_discount", "totalDiscount"]),
148
- coupon: couponFrom(data),
149
- items: items.length > 0 ? items : void 0
150
- })
56
+ ...filterUndefined({ items: mapCartItems(lineItems, currency) })
151
57
  };
152
58
  }
153
59
  function mapConvergeOrder({
@@ -155,16 +61,27 @@ function mapConvergeOrder({
155
61
  currency,
156
62
  data
157
63
  }) {
158
- const id = stringFrom(data, ["id", "order_id", "orderId"]);
159
- if (!id) {
64
+ if (!data.orderId) {
160
65
  return null;
161
66
  }
162
67
  const cart = mapConvergeCart({
163
- ...data,
164
- total_price: amount,
165
- currency
68
+ totalPrice: amount,
69
+ currency,
70
+ lineItems: data.lineItems ?? []
166
71
  });
167
- return cart ? { id, ...cart } : null;
72
+ if (!cart) {
73
+ return null;
74
+ }
75
+ return {
76
+ id: data.orderId,
77
+ ...cart,
78
+ total_tax: data.totalTax ?? 0,
79
+ total_shipping: data.totalShipping ?? 0,
80
+ ...filterUndefined({
81
+ total_discount: data.totalDiscount,
82
+ coupon: data.discountCodes
83
+ })
84
+ };
168
85
  }
169
86
  export {
170
87
  mapConvergeCart,
@@ -1,4 +1,4 @@
1
- import type { AnalyticsSink, DataPayload, PurchasePayload } from "../analytics-sink";
1
+ import type { AnalyticsSink, CartLineEventPayload, CartViewedPayload, CheckoutStartedPayload, CollectionViewedPayload, LegacyCheckoutStartedPayload, ProductViewedPayload, PurchasePayload } from "../analytics-sink";
2
2
  import type { PageMetadata } from "../utils/navigation-tracker";
3
3
  type ConvergeCall = {
4
4
  method: "track";
@@ -23,14 +23,15 @@ declare global {
23
23
  export declare class ConvergeSink implements AnalyticsSink {
24
24
  private send;
25
25
  private trackIfValid;
26
+ customEvent(): Promise<void>;
26
27
  pageView(metadata?: PageMetadata): Promise<void>;
27
28
  purchase(payload: PurchasePayload): Promise<void>;
28
29
  click(): Promise<void>;
29
- productViewed({ data }: DataPayload): Promise<void>;
30
- addToCart({ data }: DataPayload): Promise<void>;
31
- removeFromCart({ data }: DataPayload): Promise<void>;
32
- viewCart({ data }: DataPayload): Promise<void>;
33
- startCheckout({ data }: DataPayload): Promise<void>;
34
- viewCollection({ data }: DataPayload): Promise<void>;
30
+ productViewed({ data }: ProductViewedPayload): Promise<void>;
31
+ addToCart({ data }: CartLineEventPayload): Promise<void>;
32
+ removeFromCart({ data }: CartLineEventPayload): Promise<void>;
33
+ viewCart({ data }: CartViewedPayload): Promise<void>;
34
+ startCheckout(payload: CheckoutStartedPayload | LegacyCheckoutStartedPayload): Promise<void>;
35
+ viewCollection({ data }: CollectionViewedPayload): Promise<void>;
35
36
  }
36
37
  export {};
@@ -1,3 +1,4 @@
1
+ import { toCheckoutStartedData } from "../legacy-checkout";
1
2
  import { createAnalyticsQueue } from "../utils/analytics-utils";
2
3
  import {
3
4
  mapConvergeCart,
@@ -27,6 +28,8 @@ class ConvergeSink {
27
28
  }
28
29
  this.send({ method: "track", eventName, properties });
29
30
  }
31
+ async customEvent() {
32
+ }
30
33
  async pageView(metadata) {
31
34
  if (metadata?.navigationType === "initial") {
32
35
  return;
@@ -58,10 +61,25 @@ class ConvergeSink {
58
61
  this.trackIfValid("Removed From Cart", mapConvergeCartItem(data));
59
62
  }
60
63
  async viewCart({ data }) {
61
- this.trackIfValid("Viewed Cart", mapConvergeCart(data));
64
+ this.trackIfValid(
65
+ "Viewed Cart",
66
+ mapConvergeCart({
67
+ totalPrice: data.subtotal,
68
+ currency: data.currency,
69
+ lineItems: data.lineItems
70
+ })
71
+ );
62
72
  }
63
- async startCheckout({ data }) {
64
- this.trackIfValid("Started Checkout", mapConvergeCart(data));
73
+ async startCheckout(payload) {
74
+ const data = toCheckoutStartedData(payload.data);
75
+ this.trackIfValid(
76
+ "Started Checkout",
77
+ mapConvergeCart({
78
+ totalPrice: data.total,
79
+ currency: data.currency,
80
+ lineItems: data.lineItems
81
+ })
82
+ );
65
83
  }
66
84
  async viewCollection({ data }) {
67
85
  this.trackIfValid("Viewed Collection", mapConvergeCollection(data));
@@ -1,4 +1,4 @@
1
- import type { AnalyticsSink, DataPayload } from "../analytics-sink";
1
+ import type { AnalyticsSink, CartLineEventPayload, CartViewedPayload, CheckoutStartedPayload, CollectionViewedPayload, LegacyCheckoutStartedPayload, ProductViewedPayload } from "../analytics-sink";
2
2
  import type { PageMetadata } from "../utils/navigation-tracker";
3
3
  type ElevarUserProperties = {
4
4
  visitor_type: "guest" | "logged_in";
@@ -25,14 +25,16 @@ export declare class ElevarSink implements AnalyticsSink {
25
25
  constructor();
26
26
  private pushEcommerceEvent;
27
27
  private pushProductEvent;
28
+ customEvent(): Promise<void>;
28
29
  pageView(metadata?: PageMetadata): Promise<void>;
29
30
  purchase(): Promise<void>;
30
31
  click(): Promise<void>;
31
- productViewed(payload: DataPayload): Promise<void>;
32
- addToCart(payload: DataPayload): Promise<void>;
33
- removeFromCart(payload: DataPayload): Promise<void>;
34
- viewCart({ data }: DataPayload): Promise<void>;
35
- startCheckout({ data }: DataPayload): Promise<void>;
36
- viewCollection({ data }: DataPayload): Promise<void>;
32
+ productViewed({ data }: ProductViewedPayload): Promise<void>;
33
+ addToCart({ data }: CartLineEventPayload): Promise<void>;
34
+ removeFromCart({ data }: CartLineEventPayload): Promise<void>;
35
+ private cartProducts;
36
+ viewCart({ data }: CartViewedPayload): Promise<void>;
37
+ startCheckout(payload: CheckoutStartedPayload | LegacyCheckoutStartedPayload): Promise<void>;
38
+ viewCollection({ data }: CollectionViewedPayload): Promise<void>;
37
39
  }
38
40
  export {};
@@ -1,83 +1,15 @@
1
- import * as z from "zod";
1
+ import { toCheckoutStartedData } from "../legacy-checkout";
2
2
  import { legacyResourceId } from "../utils/analytics-products";
3
3
  const GUEST_USER_PROPERTIES = { visitor_type: "guest" };
4
4
  const FALLBACK_CURRENCY_CODE = "USD";
5
- const nonEmptyStringSchema = z.union([z.string().min(1), z.number().finite().transform(String)]).optional().catch(void 0);
6
- const finiteNumberSchema = z.union([
7
- z.number().finite(),
8
- z.string().trim().min(1).transform(Number).pipe(z.number().finite())
9
- ]).optional().catch(void 0);
10
- const analyticsProductSchema = z.object({
11
- productId: nonEmptyStringSchema,
12
- productTitle: nonEmptyStringSchema,
13
- variantId: nonEmptyStringSchema,
14
- variantTitle: nonEmptyStringSchema,
15
- variantSku: nonEmptyStringSchema,
16
- price: finiteNumberSchema,
17
- currency: nonEmptyStringSchema,
18
- quantity: finiteNumberSchema
19
- });
20
- const checkoutLineSchema = z.object({
21
- quantity: finiteNumberSchema,
22
- merchandise: z.object({
23
- id: nonEmptyStringSchema,
24
- title: nonEmptyStringSchema,
25
- sku: nonEmptyStringSchema,
26
- price: z.object({
27
- amount: finiteNumberSchema,
28
- currencyCode: nonEmptyStringSchema
29
- }).optional(),
30
- product: z.object({ id: nonEmptyStringSchema, title: nonEmptyStringSchema }).optional()
31
- }).optional()
32
- });
33
- const productListSchema = z.array(z.unknown()).optional().catch(void 0);
34
- const cartPayloadSchema = z.object({
35
- currency: nonEmptyStringSchema,
36
- currencyCode: nonEmptyStringSchema,
37
- subtotal: finiteNumberSchema,
38
- totalPrice: z.object({ amount: finiteNumberSchema }).optional(),
39
- lineItems: productListSchema
40
- });
41
- const collectionPayloadSchema = z.object({
42
- currency: nonEmptyStringSchema,
43
- currencyCode: nonEmptyStringSchema,
44
- products: productListSchema
45
- });
46
5
  function formatMoney(amount) {
47
6
  return amount.toFixed(2);
48
7
  }
49
- function parseCheckoutLine(line) {
50
- const parsed = checkoutLineSchema.safeParse(line);
51
- if (!parsed.success || !parsed.data.merchandise) {
52
- return null;
53
- }
54
- const { merchandise, quantity } = parsed.data;
55
- return {
56
- productId: merchandise.product?.id,
57
- productTitle: merchandise.product?.title,
58
- variantId: merchandise.id,
59
- variantTitle: merchandise.title,
60
- variantSku: merchandise.sku,
61
- price: merchandise.price?.amount,
62
- currency: merchandise.price?.currencyCode,
63
- quantity
64
- };
65
- }
66
- function parseAnalyticsProduct(value) {
67
- const parsed = analyticsProductSchema.safeParse(value);
68
- if (!parsed.success) {
69
- return null;
70
- }
71
- return parsed.data.productId ? parsed.data : parseCheckoutLine(value);
72
- }
73
8
  function toElevarProduct(product, options) {
74
9
  const productId = product.productId;
75
- if (!productId) {
76
- return null;
77
- }
78
- const variantId = product.variantId ?? productId;
10
+ const variantId = product.variantId || productId;
79
11
  return {
80
- id: product.variantSku ?? legacyResourceId(variantId),
12
+ id: product.variantSku || legacyResourceId(variantId),
81
13
  name: product.productTitle ?? "",
82
14
  brand: "",
83
15
  category: "",
@@ -93,12 +25,13 @@ function toElevarProduct(product, options) {
93
25
  };
94
26
  }
95
27
  function toElevarProducts(products, options) {
96
- const parsedProducts = products.map(parseAnalyticsProduct).filter((product) => product !== null);
97
- const currencyCode = options.currency ?? parsedProducts.find((product) => product.currency)?.currency ?? FALLBACK_CURRENCY_CODE;
98
- const elevarProducts = parsedProducts.map((product, index) => {
99
- return toElevarProduct(product, { ...options, position: index + 1 });
100
- }).filter((product) => product !== null);
101
- return { products: elevarProducts, currencyCode };
28
+ const currencyCode = options.currency ?? products.find((product) => product.currency)?.currency ?? FALLBACK_CURRENCY_CODE;
29
+ return {
30
+ products: products.map((product, index) => {
31
+ return toElevarProduct(product, { ...options, position: index + 1 });
32
+ }),
33
+ currencyCode
34
+ };
102
35
  }
103
36
  function pushToElevarDataLayer(event) {
104
37
  if (typeof window === "undefined") {
@@ -139,16 +72,11 @@ class ElevarSink {
139
72
  ecommerce
140
73
  });
141
74
  }
142
- pushProductEvent(event, action, { data }, options) {
143
- const product = parseAnalyticsProduct(data);
144
- const elevarProduct = product && toElevarProduct(product, {
75
+ pushProductEvent(event, action, product, options) {
76
+ const elevarProduct = toElevarProduct(product, {
145
77
  list: "",
146
78
  withQuantity: options.withQuantity
147
79
  });
148
- if (!elevarProduct) {
149
- console.warn(`[analytics] skipped Elevar ${event}: no product id`);
150
- return;
151
- }
152
80
  if (options.withUrl) {
153
81
  elevarProduct.url = window.location.href;
154
82
  }
@@ -160,6 +88,8 @@ class ElevarSink {
160
88
  }
161
89
  });
162
90
  }
91
+ async customEvent() {
92
+ }
163
93
  async pageView(metadata) {
164
94
  if (typeof window === "undefined") {
165
95
  return;
@@ -173,35 +103,31 @@ class ElevarSink {
173
103
  }
174
104
  async click() {
175
105
  }
176
- async productViewed(payload) {
177
- this.pushProductEvent("dl_view_item", "detail", payload, {
106
+ async productViewed({ data }) {
107
+ this.pushProductEvent("dl_view_item", "detail", data, {
178
108
  withQuantity: false
179
109
  });
180
110
  }
181
- async addToCart(payload) {
182
- this.pushProductEvent("dl_add_to_cart", "add", payload, {
111
+ async addToCart({ data }) {
112
+ this.pushProductEvent("dl_add_to_cart", "add", data, {
183
113
  withQuantity: true,
184
114
  withUrl: true
185
115
  });
186
116
  }
187
- async removeFromCart(payload) {
188
- this.pushProductEvent("dl_remove_from_cart", "remove", payload, {
117
+ async removeFromCart({ data }) {
118
+ this.pushProductEvent("dl_remove_from_cart", "remove", data, {
189
119
  withQuantity: true
190
120
  });
191
121
  }
122
+ cartProducts(cart) {
123
+ return toElevarProducts(cart.lineItems, {
124
+ list: "",
125
+ withQuantity: true,
126
+ currency: cart.currency
127
+ });
128
+ }
192
129
  async viewCart({ data }) {
193
- const cart = cartPayloadSchema.safeParse(data);
194
- if (!cart.success) {
195
- return;
196
- }
197
- const { products, currencyCode } = toElevarProducts(
198
- cart.data.lineItems ?? [],
199
- {
200
- list: "",
201
- withQuantity: true,
202
- currency: cart.data.currency ?? cart.data.currencyCode
203
- }
204
- );
130
+ const { products, currencyCode } = this.cartProducts(data);
205
131
  this.pushEcommerceEvent(
206
132
  "dl_view_cart",
207
133
  {
@@ -209,22 +135,12 @@ class ElevarSink {
209
135
  actionField: { list: "Shopping Cart" },
210
136
  impressions: products
211
137
  },
212
- formatMoney(cart.data.subtotal ?? cart.data.totalPrice?.amount ?? 0)
138
+ formatMoney(data.subtotal)
213
139
  );
214
140
  }
215
- async startCheckout({ data }) {
216
- const cart = cartPayloadSchema.safeParse(data);
217
- if (!cart.success) {
218
- return;
219
- }
220
- const { products, currencyCode } = toElevarProducts(
221
- cart.data.lineItems ?? [],
222
- {
223
- list: "",
224
- withQuantity: true,
225
- currency: cart.data.currencyCode ?? cart.data.currency
226
- }
227
- );
141
+ async startCheckout(payload) {
142
+ const data = toCheckoutStartedData(payload.data);
143
+ const { products, currencyCode } = this.cartProducts(data);
228
144
  this.pushEcommerceEvent("dl_begin_checkout", {
229
145
  currencyCode,
230
146
  checkout: {
@@ -234,18 +150,11 @@ class ElevarSink {
234
150
  });
235
151
  }
236
152
  async viewCollection({ data }) {
237
- const collection = collectionPayloadSchema.safeParse(data);
238
- if (!collection.success) {
239
- return;
240
- }
241
- const { products, currencyCode } = toElevarProducts(
242
- collection.data.products ?? [],
243
- {
244
- list: window.location.pathname,
245
- withQuantity: false,
246
- currency: collection.data.currency ?? collection.data.currencyCode
247
- }
248
- );
153
+ const { products, currencyCode } = toElevarProducts(data.products, {
154
+ list: window.location.pathname,
155
+ withQuantity: false,
156
+ currency: data.currency
157
+ });
249
158
  this.pushEcommerceEvent("dl_view_item_list", {
250
159
  currencyCode,
251
160
  impressions: products
@@ -1,15 +1,16 @@
1
- import type { AnalyticsSink, DataPayload, PurchasePayload } from "../analytics-sink";
1
+ import type { AnalyticsSink, CartLineEventPayload, CartViewedPayload, CheckoutStartedPayload, ClickPayload, CollectionViewedPayload, LegacyCheckoutStartedPayload, ProductViewedPayload, PurchasePayload } from "../analytics-sink";
2
2
  import type { PageMetadata } from "../utils/navigation-tracker";
3
3
  export declare class GA4Sink implements AnalyticsSink {
4
4
  private send;
5
5
  constructor();
6
+ customEvent(): Promise<void>;
6
7
  pageView(metadata?: PageMetadata): Promise<void>;
7
8
  purchase({ amount, currency, data }: PurchasePayload): Promise<void>;
8
- click({ data }: DataPayload): Promise<void>;
9
- productViewed({ data }: DataPayload): Promise<void>;
10
- addToCart({ data }: DataPayload): Promise<void>;
11
- removeFromCart({ data }: DataPayload): Promise<void>;
12
- viewCart({ data }: DataPayload): Promise<void>;
13
- startCheckout({ data }: DataPayload): Promise<void>;
14
- viewCollection({ data }: DataPayload): Promise<void>;
9
+ click({ data }: ClickPayload): Promise<void>;
10
+ productViewed({ data }: ProductViewedPayload): Promise<void>;
11
+ addToCart({ data }: CartLineEventPayload): Promise<void>;
12
+ removeFromCart({ data }: CartLineEventPayload): Promise<void>;
13
+ viewCart({ data }: CartViewedPayload): Promise<void>;
14
+ startCheckout(payload: CheckoutStartedPayload | LegacyCheckoutStartedPayload): Promise<void>;
15
+ viewCollection({ data }: CollectionViewedPayload): Promise<void>;
15
16
  }
@@ -1,8 +1,6 @@
1
- import {
2
- legacyResourceId,
3
- splitCollectionProducts,
4
- withoutUndefined
5
- } from "../utils/analytics-products";
1
+ import { filterUndefined } from "../../_vendor/replo-utils/lib/object.mjs";
2
+ import { toCheckoutStartedData } from "../legacy-checkout";
3
+ import { legacyResourceId } from "../utils/analytics-products";
6
4
  import { createEventQueue } from "../utils/analytics-utils";
7
5
  class GA4Sink {
8
6
  send;
@@ -16,6 +14,8 @@ class GA4Sink {
16
14
  "GA4"
17
15
  );
18
16
  }
17
+ async customEvent() {
18
+ }
19
19
  async pageView(metadata) {
20
20
  const params = metadata ? {
21
21
  page_title: metadata.title,
@@ -49,18 +49,19 @@ class GA4Sink {
49
49
  async viewCart({ data }) {
50
50
  this.send("view_cart", data);
51
51
  }
52
- async startCheckout({ data }) {
52
+ async startCheckout(payload) {
53
+ const data = toCheckoutStartedData(payload.data);
53
54
  this.send("begin_checkout", data);
54
55
  }
55
56
  async viewCollection({ data }) {
56
- const { products, rest } = splitCollectionProducts(data);
57
+ const { products, ...rest } = data;
57
58
  this.send("view_item_list", {
58
59
  item_list_id: data.collectionId,
59
60
  item_list_name: data.collectionTitle,
60
61
  currency: data.currency,
61
62
  ...products.length > 0 ? {
62
63
  items: products.map((product, index) => {
63
- return withoutUndefined({
64
+ return filterUndefined({
64
65
  item_id: legacyResourceId(product.productId),
65
66
  item_name: product.productTitle,
66
67
  item_variant: product.variantTitle,
@@ -1,5 +1,6 @@
1
- import type { AnalyticsSink, CustomEventPayload, DataPayload, PurchasePayload } from "../analytics-sink";
1
+ import type { AnalyticsSink, CartLineEventPayload, CartViewedPayload, CheckoutStartedPayload, ClickPayload, CollectionViewedPayload, CustomEventPayload, LegacyCheckoutStartedPayload, ProductViewedPayload, PurchasePayload } from "../analytics-sink";
2
2
  import type { PageMetadata } from "../utils/navigation-tracker";
3
+ /** Each mapping receives the event's typed payload. */
3
4
  export type IntelligemsEventMappings = {
4
5
  [Method in Exclude<keyof AnalyticsSink, "customEvent">]?: (...args: Parameters<AnalyticsSink[Method]>) => CustomEventPayload | null;
5
6
  };
@@ -19,11 +20,11 @@ export declare class IntelligemsSink implements AnalyticsSink {
19
20
  private send;
20
21
  pageView(metadata?: PageMetadata): Promise<void>;
21
22
  purchase(payload: PurchasePayload): Promise<void>;
22
- click(payload: DataPayload): Promise<void>;
23
- productViewed(payload: DataPayload): Promise<void>;
24
- addToCart(payload: DataPayload): Promise<void>;
25
- removeFromCart(payload: DataPayload): Promise<void>;
26
- viewCart(payload: DataPayload): Promise<void>;
27
- startCheckout(payload: DataPayload): Promise<void>;
28
- viewCollection(payload: DataPayload): Promise<void>;
23
+ click(payload: ClickPayload): Promise<void>;
24
+ productViewed(payload: ProductViewedPayload): Promise<void>;
25
+ addToCart(payload: CartLineEventPayload): Promise<void>;
26
+ removeFromCart(payload: CartLineEventPayload): Promise<void>;
27
+ viewCart(payload: CartViewedPayload): Promise<void>;
28
+ startCheckout(payload: CheckoutStartedPayload | LegacyCheckoutStartedPayload): Promise<void>;
29
+ viewCollection(payload: CollectionViewedPayload): Promise<void>;
29
30
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { consentStore, isConsentAllowed } from "../../consent/consent-store";
3
+ import { toCheckoutStartedData } from "../legacy-checkout";
3
4
  class IntelligemsSink {
4
5
  constructor(options) {
5
6
  this.options = options;
@@ -55,7 +56,8 @@ class IntelligemsSink {
55
56
  await this.send(this.options.events?.viewCart?.(payload));
56
57
  }
57
58
  async startCheckout(payload) {
58
- await this.send(this.options.events?.startCheckout?.(payload));
59
+ const data = toCheckoutStartedData(payload.data);
60
+ await this.send(this.options.events?.startCheckout?.({ data }));
59
61
  }
60
62
  async viewCollection(payload) {
61
63
  await this.send(this.options.events?.viewCollection?.(payload));