@replohq/sdk 1.22.0 → 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.
- package/_vendor/replo-utils/lib/json.mjs +4 -5
- package/_vendor/replo-utils/lib/misc.mjs +4 -3
- package/_vendor/replo-utils/lib/object.d.ts +16 -1
- package/_vendor/replo-utils/lib/object.mjs +3 -4
- package/_vendor/schemas/contentEntry.mjs +3 -3
- package/_vendor/schemas/contentManifest.mjs +6 -6
- package/_vendor/schemas/errors.d.ts +3 -43
- package/_vendor/schemas/{money.d.ts → moneyFormat.d.ts} +1 -8
- package/_vendor/schemas/{money.mjs → moneyFormat.mjs} +5 -16
- package/_vendor/schemas/reploError.d.ts +43 -0
- package/_vendor/schemas/routing/locale.mjs +6 -4
- package/_vendor/schemas/routing/rules.mjs +6 -4
- package/analytics/analytics-sink.d.ts +126 -14
- package/analytics/combine-sinks.js +36 -13
- package/analytics/hooks/use-product-viewed-analytics.d.ts +1 -17
- package/analytics/hooks/use-product-viewed-analytics.js +5 -14
- package/analytics/legacy-checkout.d.ts +2 -0
- package/analytics/legacy-checkout.js +26 -0
- package/analytics/sinks/converge-event-mapper.d.ts +10 -11
- package/analytics/sinks/converge-event-mapper.js +50 -133
- package/analytics/sinks/converge-sink.d.ts +8 -7
- package/analytics/sinks/converge-sink.js +21 -3
- package/analytics/sinks/elevar-sink.d.ts +9 -7
- package/analytics/sinks/elevar-sink.js +37 -128
- package/analytics/sinks/ga4-sink.d.ts +9 -8
- package/analytics/sinks/ga4-sink.js +9 -8
- package/analytics/sinks/intelligems-sink.d.ts +9 -8
- package/analytics/sinks/intelligems-sink.js +3 -1
- package/analytics/sinks/meta-sink.d.ts +5 -4
- package/analytics/sinks/meta-sink.js +7 -3
- package/analytics/sinks/northbeam-sink.d.ts +1 -0
- package/analytics/sinks/northbeam-sink.js +2 -0
- package/analytics/sinks/pinterest-sink.d.ts +7 -6
- package/analytics/sinks/pinterest-sink.js +14 -20
- package/analytics/sinks/reddit-sink.d.ts +8 -7
- package/analytics/sinks/reddit-sink.js +13 -20
- package/analytics/sinks/replo-sink.d.ts +21 -9
- package/analytics/sinks/replo-sink.js +37 -39
- package/analytics/sinks/snapchat-sink.d.ts +6 -5
- package/analytics/sinks/snapchat-sink.js +8 -8
- package/analytics/sinks/tiktok-sink.d.ts +8 -7
- package/analytics/sinks/tiktok-sink.js +10 -15
- package/analytics/sinks/window-sink.d.ts +11 -9
- package/analytics/sinks/window-sink.js +5 -1
- package/analytics/sinks/x-sink.d.ts +5 -4
- package/analytics/sinks/x-sink.js +19 -50
- package/analytics/test-fixtures.d.ts +5 -0
- package/analytics/test-fixtures.js +18 -0
- package/analytics/utils/analytics-products.d.ts +0 -30
- package/analytics/utils/analytics-products.js +1 -51
- package/analytics/utils/collection-analytics.d.ts +2 -15
- package/analytics/utils/collection-analytics.js +14 -18
- package/analytics/utils/product-analytics.d.ts +23 -0
- package/analytics/utils/product-analytics.js +21 -0
- package/cart/hooks/use-add-to-cart.js +1 -1
- package/cart/utils/cart-analytics.d.ts +3 -23
- package/cart/utils/cart-analytics.js +1 -1
- package/cart/utils/cart-utils.js +1 -1
- package/cart/utils/variant-to-cart-line.js +1 -1
- package/chunk-CKRRL66R.mjs +28 -0
- package/{chunk-VVB7BEDE.mjs → chunk-O4QBR4QC.mjs} +9 -4
- package/{chunk-EUIVDITZ.mjs → chunk-OPKMOW43.mjs} +1 -1
- package/{chunk-C37TXOGI.mjs → chunk-PSYP2DYM.mjs} +1 -1
- package/{chunk-ACQS4AG5.mjs → chunk-TTEBDCWT.mjs} +272 -109
- package/{chunk-HFKL4ZR5.mjs → chunk-XGXJOHUY.mjs} +2 -1
- package/{chunk-AQG3256R.mjs → chunk-XSMYSAKY.mjs} +0 -26
- package/{chunk-SSBIMQES.mjs → chunk-XWWFRIXV.mjs} +36 -99
- package/chunk-ZPDXVFCR.mjs +66 -0
- package/hooks/use-formatted-price.js +1 -1
- package/lib/buildMetadata.js +3 -3
- package/loaders/collection-loader.js +8 -6
- package/loaders/collection-products-loader.js +8 -6
- package/loaders/contentful-entries-loader.js +5 -3
- package/loaders/contentful-entry-loader.js +5 -3
- package/loaders/integration-loader-schemas.d.ts +260 -0
- package/loaders/integration-loader-schemas.js +55 -0
- package/loaders/invoke-loader.d.ts +5 -0
- package/loaders/invoke-loader.js +1 -1
- package/loaders/judgeme-review-aggregate-loader.d.ts +1 -1
- package/loaders/judgeme-review-aggregate-loader.js +10 -6
- package/loaders/judgeme-reviews-loader.d.ts +1 -1
- package/loaders/judgeme-reviews-loader.js +5 -3
- package/loaders/kaching-bundles-loader.js +5 -3
- package/loaders/levanta-product-loader.js +8 -6
- package/loaders/loox-review-aggregate-loader.d.ts +1 -1
- package/loaders/loox-review-aggregate-loader.js +10 -6
- package/loaders/loox-reviews-loader.d.ts +1 -1
- package/loaders/loox-reviews-loader.js +8 -6
- package/loaders/metaobject-loader.js +5 -3
- package/loaders/metaobjects-loader.js +5 -3
- package/loaders/okendo-review-aggregate-loader.d.ts +2 -7
- package/loaders/okendo-review-aggregate-loader.js +8 -12
- package/loaders/okendo-reviews-loader.d.ts +2 -42
- package/loaders/okendo-reviews-loader.js +5 -8
- package/loaders/product-loader.js +5 -3
- package/loaders/rebuy-recommendations-loader.d.ts +2 -167
- package/loaders/rebuy-recommendations-loader.js +8 -10
- package/loaders/reviews-io-review-aggregate-loader.d.ts +1 -1
- package/loaders/reviews-io-review-aggregate-loader.js +5 -3
- package/loaders/reviews-io-reviews-loader.d.ts +1 -1
- package/loaders/reviews-io-reviews-loader.js +7 -3
- package/loaders/shopify-integration-details-loader.js +10 -6
- package/loaders/smile-earning-rules-loader.d.ts +2 -8
- package/loaders/smile-earning-rules-loader.js +8 -16
- package/loaders/smile-rewards-loader.d.ts +2 -8
- package/loaders/smile-rewards-loader.js +8 -16
- package/loaders/smile-vip-tiers-loader.d.ts +2 -7
- package/loaders/smile-vip-tiers-loader.js +8 -15
- package/loaders/statsig-experiment-loader.js +5 -3
- package/loaders/yotpo-review-aggregate-loader.d.ts +1 -1
- package/loaders/yotpo-review-aggregate-loader.js +10 -6
- package/loaders/yotpo-reviews-loader.d.ts +1 -1
- package/loaders/yotpo-reviews-loader.js +5 -3
- package/money.d.ts +1 -1
- package/money.js +1 -1
- package/package.json +8 -4
- package/chunk-CQYCPDPI.mjs +0 -166
|
@@ -1,153 +1,59 @@
|
|
|
1
1
|
import { filterUndefined } from "../../_vendor/replo-utils/lib/object.mjs";
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
47
|
-
|
|
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(
|
|
87
|
-
|
|
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
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
|
111
|
-
|
|
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
|
-
|
|
118
|
-
const name = stringFrom(data, ["name", "collectionTitle"]);
|
|
119
|
-
if (!id || !name) {
|
|
33
|
+
if (!data.collectionTitle) {
|
|
120
34
|
return null;
|
|
121
35
|
}
|
|
122
|
-
const items =
|
|
36
|
+
const items = data.products.flatMap((line) => mapProduct(line) ?? []);
|
|
123
37
|
return {
|
|
124
|
-
id,
|
|
125
|
-
name,
|
|
126
|
-
...
|
|
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(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (
|
|
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:
|
|
144
|
-
total_shipping:
|
|
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
|
-
|
|
159
|
-
if (!id) {
|
|
64
|
+
if (!data.orderId) {
|
|
160
65
|
return null;
|
|
161
66
|
}
|
|
162
67
|
const cart = mapConvergeCart({
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
68
|
+
totalPrice: amount,
|
|
69
|
+
currency,
|
|
70
|
+
lineItems: data.lineItems ?? []
|
|
166
71
|
});
|
|
167
|
-
|
|
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,
|
|
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 }:
|
|
30
|
-
addToCart({ data }:
|
|
31
|
-
removeFromCart({ data }:
|
|
32
|
-
viewCart({ data }:
|
|
33
|
-
startCheckout(
|
|
34
|
-
viewCollection({ data }:
|
|
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(
|
|
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(
|
|
64
|
-
|
|
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,
|
|
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(
|
|
32
|
-
addToCart(
|
|
33
|
-
removeFromCart(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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
|
-
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
const variantId = product.variantId ?? productId;
|
|
10
|
+
const variantId = product.variantId || productId;
|
|
79
11
|
return {
|
|
80
|
-
id: product.variantSku
|
|
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
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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,
|
|
143
|
-
const
|
|
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(
|
|
177
|
-
this.pushProductEvent("dl_view_item", "detail",
|
|
106
|
+
async productViewed({ data }) {
|
|
107
|
+
this.pushProductEvent("dl_view_item", "detail", data, {
|
|
178
108
|
withQuantity: false
|
|
179
109
|
});
|
|
180
110
|
}
|
|
181
|
-
async addToCart(
|
|
182
|
-
this.pushProductEvent("dl_add_to_cart", "add",
|
|
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(
|
|
188
|
-
this.pushProductEvent("dl_remove_from_cart", "remove",
|
|
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
|
|
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(
|
|
138
|
+
formatMoney(data.subtotal)
|
|
213
139
|
);
|
|
214
140
|
}
|
|
215
|
-
async startCheckout(
|
|
216
|
-
const
|
|
217
|
-
|
|
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
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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,
|
|
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 }:
|
|
9
|
-
productViewed({ data }:
|
|
10
|
-
addToCart({ data }:
|
|
11
|
-
removeFromCart({ data }:
|
|
12
|
-
viewCart({ data }:
|
|
13
|
-
startCheckout(
|
|
14
|
-
viewCollection({ data }:
|
|
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
|
-
|
|
3
|
-
|
|
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(
|
|
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 } =
|
|
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
|
|
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,
|
|
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:
|
|
23
|
-
productViewed(payload:
|
|
24
|
-
addToCart(payload:
|
|
25
|
-
removeFromCart(payload:
|
|
26
|
-
viewCart(payload:
|
|
27
|
-
startCheckout(payload:
|
|
28
|
-
viewCollection(payload:
|
|
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
|
-
|
|
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));
|