@anker-in/shopify-react 1.1.1 → 1.2.0-beta.1
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/dist/hooks/index.d.mts +39 -44
- package/dist/hooks/index.d.ts +39 -44
- package/dist/hooks/index.js +349 -93
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +342 -94
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +438 -116
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +427 -117
- package/dist/index.mjs.map +1 -1
- package/dist/provider/index.d.mts +26 -14
- package/dist/provider/index.d.ts +26 -14
- package/dist/provider/index.js +155 -32
- package/dist/provider/index.js.map +1 -1
- package/dist/provider/index.mjs +155 -32
- package/dist/provider/index.mjs.map +1 -1
- package/dist/{types-CMMWxyUF.d.mts → types-C4qc-wG4.d.mts} +167 -7
- package/dist/{types-CMMWxyUF.d.ts → types-C4qc-wG4.d.ts} +167 -7
- package/package.json +17 -17
package/dist/index.js
CHANGED
|
@@ -885,15 +885,23 @@ var trackAddToCartGA = ({
|
|
|
885
885
|
currency: currencyCode,
|
|
886
886
|
value: totalPrice,
|
|
887
887
|
position: gtmParams?.position || "",
|
|
888
|
-
items: lineItems.map((
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
888
|
+
items: lineItems.map((item) => {
|
|
889
|
+
const imageUrl = item.variant?.image?.url || item.variant?.product?.images?.[0]?.url;
|
|
890
|
+
const itemCategoryId = item.gtmParams?.item_category_id;
|
|
891
|
+
const itemVariantId = item.variant?.id ? shopifyCore.atobID(item.variant.id) : void 0;
|
|
892
|
+
return {
|
|
893
|
+
item_id: item.variant?.sku,
|
|
894
|
+
item_name: item.variant?.product?.title || item.variant?.product?.title,
|
|
895
|
+
item_brand: gtmParams?.brand || "",
|
|
896
|
+
item_category: item.variant?.product?.productType || "",
|
|
897
|
+
item_variant: item.variant?.title || item.variant?.title,
|
|
898
|
+
price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
|
|
899
|
+
quantity: item.quantity || 1,
|
|
900
|
+
...imageUrl && { image_url: imageUrl },
|
|
901
|
+
...itemCategoryId && { item_category_id: itemCategoryId },
|
|
902
|
+
...itemVariantId && { item_variant_id: itemVariantId }
|
|
903
|
+
};
|
|
904
|
+
}),
|
|
897
905
|
...gtmParams?.ga4Params
|
|
898
906
|
}
|
|
899
907
|
});
|
|
@@ -920,15 +928,23 @@ var trackBeginCheckoutGA = ({
|
|
|
920
928
|
position: gtmParams?.position,
|
|
921
929
|
currency: currencyCode,
|
|
922
930
|
value: totalPrice,
|
|
923
|
-
items: lineItems.map((item) =>
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
931
|
+
items: lineItems.map((item) => {
|
|
932
|
+
const imageUrl = item.variant?.image?.url || item.variant?.product?.images?.[0]?.url;
|
|
933
|
+
const itemCategoryId = item.gtmParams?.item_category_id;
|
|
934
|
+
const itemVariantId = item.variant?.id ? shopifyCore.atobID(item.variant.id) : void 0;
|
|
935
|
+
return {
|
|
936
|
+
item_id: item.variant?.sku,
|
|
937
|
+
item_name: item.variant?.product?.title,
|
|
938
|
+
item_brand: gtmParams?.brand || "",
|
|
939
|
+
item_category: item.variant?.product?.productType,
|
|
940
|
+
item_variant: item.variant?.title,
|
|
941
|
+
price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
|
|
942
|
+
quantity: item.quantity || 1,
|
|
943
|
+
...imageUrl && { image_url: imageUrl },
|
|
944
|
+
...itemCategoryId !== void 0 && { item_category_id: itemCategoryId },
|
|
945
|
+
...itemVariantId && { item_variant_id: itemVariantId }
|
|
946
|
+
};
|
|
947
|
+
}),
|
|
932
948
|
...gtmParams?.ga4Params
|
|
933
949
|
}
|
|
934
950
|
});
|
|
@@ -956,19 +972,111 @@ var trackBuyNowGA = ({
|
|
|
956
972
|
position: gtmParams?.position,
|
|
957
973
|
currency: currencyCode,
|
|
958
974
|
value: totalPrice,
|
|
959
|
-
items: lineItems.map((item) =>
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
975
|
+
items: lineItems.map((item) => {
|
|
976
|
+
const imageUrl = item.variant?.image?.url || item.variant?.product?.images?.[0]?.url;
|
|
977
|
+
const itemCategoryId = item.gtmParams?.item_category_id;
|
|
978
|
+
const itemVariantId = item.variant?.id ? shopifyCore.atobID(item.variant.id) : void 0;
|
|
979
|
+
return {
|
|
980
|
+
item_id: item.variant?.sku,
|
|
981
|
+
item_name: item.variant?.product?.title || item.variant?.title,
|
|
982
|
+
item_brand: gtmParams?.brand || "",
|
|
983
|
+
item_category: item.variant?.product?.productType || "",
|
|
984
|
+
item_variant: item.variant?.title,
|
|
985
|
+
price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
|
|
986
|
+
quantity: item.quantity || 1,
|
|
987
|
+
...imageUrl && { image_url: imageUrl },
|
|
988
|
+
...itemCategoryId !== void 0 && { item_category_id: itemCategoryId },
|
|
989
|
+
...itemVariantId && { item_variant_id: itemVariantId }
|
|
990
|
+
};
|
|
991
|
+
}),
|
|
968
992
|
...gtmParams?.ga4Params
|
|
969
993
|
}
|
|
970
994
|
});
|
|
971
995
|
};
|
|
996
|
+
function waitForGtagReady(timeout = 1e4) {
|
|
997
|
+
return new Promise((resolve, reject) => {
|
|
998
|
+
const start = Date.now();
|
|
999
|
+
function check() {
|
|
1000
|
+
if (typeof window !== "undefined" && typeof window.gtag !== "undefined") {
|
|
1001
|
+
resolve();
|
|
1002
|
+
} else if (Date.now() - start > timeout) {
|
|
1003
|
+
reject(new Error("GA4 gtag not loaded"));
|
|
1004
|
+
} else {
|
|
1005
|
+
setTimeout(check, 50);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
check();
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
var getGA4ClientId = async (measurementId = "G-R0BRMRK4CY") => {
|
|
1012
|
+
try {
|
|
1013
|
+
await waitForGtagReady();
|
|
1014
|
+
return new Promise((resolve, reject) => {
|
|
1015
|
+
if (!window.gtag) {
|
|
1016
|
+
reject(new Error("gtag is not defined"));
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
window.gtag("get", measurementId, "client_id", (clientId) => {
|
|
1020
|
+
if (clientId) {
|
|
1021
|
+
resolve(clientId);
|
|
1022
|
+
} else {
|
|
1023
|
+
reject(new Error("Failed to get client_id"));
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
});
|
|
1027
|
+
} catch (error) {
|
|
1028
|
+
console.error("Failed to get GA4 client_id:", error);
|
|
1029
|
+
return "";
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
var getGA4SessionId = async (measurementId = "G-R0BRMRK4CY") => {
|
|
1033
|
+
try {
|
|
1034
|
+
await waitForGtagReady();
|
|
1035
|
+
return new Promise((resolve) => {
|
|
1036
|
+
if (!window.gtag) {
|
|
1037
|
+
resolve("");
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
window.gtag("get", measurementId, "session_id", (sessionId) => {
|
|
1041
|
+
resolve(sessionId || "");
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
} catch (error) {
|
|
1045
|
+
console.error("Failed to get GA4 session_id:", error);
|
|
1046
|
+
return "";
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
var getGA4Data = async (measurementId = "G-R0BRMRK4CY") => {
|
|
1050
|
+
try {
|
|
1051
|
+
await waitForGtagReady();
|
|
1052
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
1053
|
+
setTimeout(() => {
|
|
1054
|
+
resolve({ clientId: "", sessionId: "" });
|
|
1055
|
+
}, 300);
|
|
1056
|
+
});
|
|
1057
|
+
const dataPromise = new Promise((resolve) => {
|
|
1058
|
+
if (!window.gtag) {
|
|
1059
|
+
resolve({ clientId: "", sessionId: "" });
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
window.gtag("get", measurementId, "client_id", (clientId) => {
|
|
1063
|
+
window.gtag("get", measurementId, "session_id", (sessionId) => {
|
|
1064
|
+
resolve({
|
|
1065
|
+
clientId: clientId || "",
|
|
1066
|
+
sessionId: sessionId || ""
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
return Promise.race([dataPromise, timeoutPromise]);
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
console.error("Failed to get GA4 data:", error);
|
|
1074
|
+
return {
|
|
1075
|
+
clientId: "",
|
|
1076
|
+
sessionId: ""
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
972
1080
|
|
|
973
1081
|
// src/tracking/fbq.ts
|
|
974
1082
|
var trackAddToCartFBQ = ({ lineItems = [] }) => {
|
|
@@ -1151,16 +1259,155 @@ var getLinesWithAttributes = ({
|
|
|
1151
1259
|
return functionLine;
|
|
1152
1260
|
});
|
|
1153
1261
|
};
|
|
1262
|
+
function useRemoveCartLines(options) {
|
|
1263
|
+
const { client, locale, cartCookieAdapter } = useShopify();
|
|
1264
|
+
const { mutateCart, metafieldIdentifiers } = useCartContext();
|
|
1265
|
+
const removeLines = react.useCallback(
|
|
1266
|
+
async (_key, { arg }) => {
|
|
1267
|
+
const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
|
|
1268
|
+
let updatedCart = await shopifySdk.removeCartLines(client, {
|
|
1269
|
+
cartId,
|
|
1270
|
+
lineIds,
|
|
1271
|
+
metafieldIdentifiers,
|
|
1272
|
+
cookieAdapter: cartCookieAdapter
|
|
1273
|
+
});
|
|
1274
|
+
if (updatedCart && autoRemoveInvalidCodes) {
|
|
1275
|
+
const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
|
|
1276
|
+
if (unApplicableCodes.length > 0) {
|
|
1277
|
+
if (onCodesRemoved) {
|
|
1278
|
+
const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
|
|
1279
|
+
if (handledCart) {
|
|
1280
|
+
updatedCart = handledCart;
|
|
1281
|
+
}
|
|
1282
|
+
} else {
|
|
1283
|
+
updatedCart = await shopifySdk.updateCartCodes(client, {
|
|
1284
|
+
cartId: updatedCart.id,
|
|
1285
|
+
discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
|
|
1286
|
+
metafieldIdentifiers,
|
|
1287
|
+
cookieAdapter: cartCookieAdapter
|
|
1288
|
+
}) || updatedCart;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (updatedCart) {
|
|
1293
|
+
mutateCart(updatedCart);
|
|
1294
|
+
}
|
|
1295
|
+
return updatedCart;
|
|
1296
|
+
},
|
|
1297
|
+
[client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
|
|
1298
|
+
);
|
|
1299
|
+
return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// src/hooks/cart/feature/use-auto-remove-free-gifts.ts
|
|
1303
|
+
function useAutoRemoveFreeGifts(options = {}) {
|
|
1304
|
+
const {
|
|
1305
|
+
removeFunctionGifts = true,
|
|
1306
|
+
removeScriptGifts = true,
|
|
1307
|
+
isGiftLineItem
|
|
1308
|
+
} = options;
|
|
1309
|
+
const [isRemoving, setIsRemoving] = react.useState(false);
|
|
1310
|
+
const { cart } = useCartContext();
|
|
1311
|
+
const { trigger: removeCartLines2 } = useRemoveCartLines();
|
|
1312
|
+
const giftsToRemove = react.useMemo(() => {
|
|
1313
|
+
if (!cart?.lineItems) {
|
|
1314
|
+
return [];
|
|
1315
|
+
}
|
|
1316
|
+
return cart.lineItems.filter((item) => {
|
|
1317
|
+
if (removeFunctionGifts) {
|
|
1318
|
+
const functionAttr = item.customAttributes?.find(
|
|
1319
|
+
(attr) => attr.key === "_discounts_function_env"
|
|
1320
|
+
)?.value;
|
|
1321
|
+
if (functionAttr) {
|
|
1322
|
+
try {
|
|
1323
|
+
const functionAttrObj = JSON.parse(functionAttr);
|
|
1324
|
+
if (functionAttrObj.is_gift && functionAttrObj.rule_id && functionAttrObj.spend_sum_money) {
|
|
1325
|
+
return true;
|
|
1326
|
+
}
|
|
1327
|
+
} catch (error) {
|
|
1328
|
+
console.error("Failed to parse _discounts_function_env:", error);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
if (removeScriptGifts) {
|
|
1333
|
+
const scriptGiftAttr = item.customAttributes?.find(
|
|
1334
|
+
(attr) => attr.key === "_giveaway_gradient_gifts"
|
|
1335
|
+
);
|
|
1336
|
+
if (scriptGiftAttr) {
|
|
1337
|
+
return true;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
if (isGiftLineItem && isGiftLineItem(item)) {
|
|
1341
|
+
return true;
|
|
1342
|
+
}
|
|
1343
|
+
return false;
|
|
1344
|
+
});
|
|
1345
|
+
}, [cart, removeFunctionGifts, removeScriptGifts, isGiftLineItem]);
|
|
1346
|
+
react.useEffect(() => {
|
|
1347
|
+
if (isRemoving || giftsToRemove.length === 0) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const performRemoval = async () => {
|
|
1351
|
+
setIsRemoving(true);
|
|
1352
|
+
try {
|
|
1353
|
+
await removeCartLines2({
|
|
1354
|
+
lineIds: giftsToRemove.map((item) => item.id)
|
|
1355
|
+
});
|
|
1356
|
+
} catch (error) {
|
|
1357
|
+
console.error("Failed to remove free gifts:", error);
|
|
1358
|
+
} finally {
|
|
1359
|
+
setIsRemoving(false);
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
performRemoval();
|
|
1363
|
+
}, [
|
|
1364
|
+
isRemoving,
|
|
1365
|
+
giftsToRemove,
|
|
1366
|
+
removeCartLines2
|
|
1367
|
+
]);
|
|
1368
|
+
return {
|
|
1369
|
+
isRemoving
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
function isFunctionGift(line) {
|
|
1373
|
+
const functionAttr = line.customAttributes?.find(
|
|
1374
|
+
(attr) => attr.key === "_discounts_function_env"
|
|
1375
|
+
)?.value;
|
|
1376
|
+
if (!functionAttr) {
|
|
1377
|
+
return false;
|
|
1378
|
+
}
|
|
1379
|
+
try {
|
|
1380
|
+
const functionAttrObj = JSON.parse(functionAttr);
|
|
1381
|
+
return Boolean(
|
|
1382
|
+
functionAttrObj.is_gift && functionAttrObj.rule_id && functionAttrObj.spend_sum_money
|
|
1383
|
+
);
|
|
1384
|
+
} catch {
|
|
1385
|
+
return false;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
function isScriptGift(line) {
|
|
1389
|
+
return line.customAttributes?.some(
|
|
1390
|
+
(attr) => attr.key === "_giveaway_gradient_gifts"
|
|
1391
|
+
) ?? false;
|
|
1392
|
+
}
|
|
1393
|
+
function isBuyGetGift(line) {
|
|
1394
|
+
return line.customAttributes?.some(
|
|
1395
|
+
(attr) => attr.key === "_freegift_related_handlesku"
|
|
1396
|
+
) ?? false;
|
|
1397
|
+
}
|
|
1398
|
+
function isAnyGift(line) {
|
|
1399
|
+
return isFunctionGift(line) || isScriptGift(line) || isBuyGetGift(line);
|
|
1400
|
+
}
|
|
1154
1401
|
function useCalcGiftsFromLines({
|
|
1155
1402
|
lines,
|
|
1156
1403
|
customer,
|
|
1157
1404
|
scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
|
|
1158
1405
|
}) {
|
|
1159
1406
|
const { locale } = useShopify();
|
|
1160
|
-
const { cart,
|
|
1161
|
-
const functionGift = useCalcAutoFreeGift(cart,
|
|
1407
|
+
const { cart, functionAutoFreeGiftConfig, scriptAutoFreeGiftConfig } = useCartContext();
|
|
1408
|
+
const functionGift = useCalcAutoFreeGift(cart, functionAutoFreeGiftConfig || [], customer, lines);
|
|
1162
1409
|
const scriptGift = useScriptAutoFreeGift({
|
|
1163
|
-
campaign:
|
|
1410
|
+
campaign: scriptAutoFreeGiftConfig,
|
|
1164
1411
|
_giveaway: scriptGiveawayKey,
|
|
1165
1412
|
cart,
|
|
1166
1413
|
locale,
|
|
@@ -1195,7 +1442,9 @@ function useCalcGiftsFromLines({
|
|
|
1195
1442
|
const variants = product?.variants;
|
|
1196
1443
|
const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
|
|
1197
1444
|
if (!variant) {
|
|
1198
|
-
console.warn(
|
|
1445
|
+
console.warn(
|
|
1446
|
+
`Script gift: Variant not found for handle=${item.handle}, sku=${item.sku}`
|
|
1447
|
+
);
|
|
1199
1448
|
return null;
|
|
1200
1449
|
}
|
|
1201
1450
|
return {
|
|
@@ -1338,6 +1587,19 @@ var getReferralAttributes = () => {
|
|
|
1338
1587
|
}
|
|
1339
1588
|
return [];
|
|
1340
1589
|
};
|
|
1590
|
+
var getOperatingSystem = () => {
|
|
1591
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
1592
|
+
return "Unknown";
|
|
1593
|
+
}
|
|
1594
|
+
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
|
1595
|
+
if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
|
|
1596
|
+
return "IOS";
|
|
1597
|
+
}
|
|
1598
|
+
if (/android/i.test(userAgent)) {
|
|
1599
|
+
return "Android";
|
|
1600
|
+
}
|
|
1601
|
+
return "Unknown";
|
|
1602
|
+
};
|
|
1341
1603
|
var getUserType = (customer) => {
|
|
1342
1604
|
let userInfo = Cookies5__default.default.get("userInfo");
|
|
1343
1605
|
if (userInfo) {
|
|
@@ -1359,12 +1621,42 @@ var getUserType = (customer) => {
|
|
|
1359
1621
|
}
|
|
1360
1622
|
return "new_user_login";
|
|
1361
1623
|
};
|
|
1362
|
-
function
|
|
1624
|
+
function getGA4Attributes(ga4Data) {
|
|
1625
|
+
if (!ga4Data?.clientId && !ga4Data?.sessionId) {
|
|
1626
|
+
return [];
|
|
1627
|
+
}
|
|
1628
|
+
const attributes = [];
|
|
1629
|
+
if (ga4Data.clientId) {
|
|
1630
|
+
attributes.push({
|
|
1631
|
+
key: "_ga4_client_id",
|
|
1632
|
+
value: ga4Data.clientId
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
if (ga4Data.sessionId) {
|
|
1636
|
+
attributes.push({
|
|
1637
|
+
key: "_ga4_session_id",
|
|
1638
|
+
value: ga4Data.sessionId
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
return attributes;
|
|
1642
|
+
}
|
|
1643
|
+
async function getGA4AttributesAsync() {
|
|
1644
|
+
try {
|
|
1645
|
+
const ga4Data = await getGA4Data();
|
|
1646
|
+
return getGA4Attributes(ga4Data);
|
|
1647
|
+
} catch (error) {
|
|
1648
|
+
console.error("Failed to get GA4 attributes:", error);
|
|
1649
|
+
return [];
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
function getCartBasicAttributes({
|
|
1363
1653
|
profile,
|
|
1364
1654
|
customer,
|
|
1365
1655
|
cart,
|
|
1366
1656
|
memberType,
|
|
1367
|
-
currentUrl = ""
|
|
1657
|
+
currentUrl = "",
|
|
1658
|
+
appContext,
|
|
1659
|
+
buyPath
|
|
1368
1660
|
}) {
|
|
1369
1661
|
const userType = getUserType(customer);
|
|
1370
1662
|
const memberAttributes = [
|
|
@@ -1391,12 +1683,10 @@ function getCartAttributes({
|
|
|
1391
1683
|
value: "1"
|
|
1392
1684
|
});
|
|
1393
1685
|
}
|
|
1394
|
-
const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
|
|
1395
1686
|
const functionAttributes = [
|
|
1396
1687
|
{
|
|
1397
1688
|
key: CUSTOMER_ATTRIBUTE_KEY,
|
|
1398
1689
|
value: JSON.stringify({
|
|
1399
|
-
discount_code: discountCodes,
|
|
1400
1690
|
user_tags: customer?.tags || []
|
|
1401
1691
|
})
|
|
1402
1692
|
}
|
|
@@ -1404,26 +1694,38 @@ function getCartAttributes({
|
|
|
1404
1694
|
const presellAttributes = [
|
|
1405
1695
|
{
|
|
1406
1696
|
key: "_presale",
|
|
1407
|
-
value: cart?.lineItems
|
|
1697
|
+
value: cart?.lineItems?.some((item) => item?.variant?.metafields?.presell === "presell")
|
|
1408
1698
|
}
|
|
1409
1699
|
];
|
|
1410
1700
|
const weightAttributes = [
|
|
1411
1701
|
{
|
|
1412
1702
|
key: "_weight",
|
|
1413
|
-
value: cart?.lineItems
|
|
1703
|
+
value: cart?.lineItems?.reduce((acc, item) => {
|
|
1414
1704
|
const itemWeight = new Decimal2__default.default(item.variant.weight ?? 0).times(item.quantity);
|
|
1415
1705
|
return new Decimal2__default.default(acc).plus(itemWeight).toNumber();
|
|
1416
1706
|
}, 0).toString()
|
|
1417
|
-
},
|
|
1418
|
-
{
|
|
1419
|
-
key: "_app_source_name",
|
|
1420
|
-
value: "dtc"
|
|
1421
1707
|
}
|
|
1422
1708
|
];
|
|
1423
1709
|
const trackingAttributes = [
|
|
1424
1710
|
{
|
|
1425
1711
|
key: "utm_params",
|
|
1426
1712
|
value: currentUrl
|
|
1713
|
+
},
|
|
1714
|
+
{
|
|
1715
|
+
key: "_app_source_name",
|
|
1716
|
+
value: appContext?.isInApp && appContext?.appName ? appContext.appName : "dtc"
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
key: "_operating_system",
|
|
1720
|
+
value: getOperatingSystem()
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
key: "_cart_id",
|
|
1724
|
+
value: cart?.id
|
|
1725
|
+
},
|
|
1726
|
+
{
|
|
1727
|
+
key: "_buy_path",
|
|
1728
|
+
value: buyPath
|
|
1427
1729
|
}
|
|
1428
1730
|
];
|
|
1429
1731
|
const commonAttributes = [
|
|
@@ -1443,21 +1745,41 @@ var useCartAttributes = ({
|
|
|
1443
1745
|
profile,
|
|
1444
1746
|
customer,
|
|
1445
1747
|
cart,
|
|
1446
|
-
memberType
|
|
1748
|
+
memberType,
|
|
1749
|
+
appContext,
|
|
1750
|
+
buyPath
|
|
1447
1751
|
}) => {
|
|
1448
1752
|
const [currentUrl, setCurrentUrl] = react.useState("");
|
|
1753
|
+
const [ga4Data, setGa4Data] = react.useState(null);
|
|
1449
1754
|
react.useEffect(() => {
|
|
1450
1755
|
setCurrentUrl(window.location.href);
|
|
1451
1756
|
}, []);
|
|
1757
|
+
react.useEffect(() => {
|
|
1758
|
+
let isMounted = true;
|
|
1759
|
+
getGA4Data().then((data) => {
|
|
1760
|
+
if (isMounted) {
|
|
1761
|
+
setGa4Data(data);
|
|
1762
|
+
}
|
|
1763
|
+
}).catch((error) => {
|
|
1764
|
+
console.error("Failed to get GA4 data in useCartAttributes:", error);
|
|
1765
|
+
});
|
|
1766
|
+
return () => {
|
|
1767
|
+
isMounted = false;
|
|
1768
|
+
};
|
|
1769
|
+
}, []);
|
|
1452
1770
|
const attributes = react.useMemo(() => {
|
|
1453
|
-
|
|
1771
|
+
const basicAttributes = getCartBasicAttributes({
|
|
1454
1772
|
profile,
|
|
1455
1773
|
customer,
|
|
1456
1774
|
cart,
|
|
1457
1775
|
memberType,
|
|
1458
|
-
currentUrl
|
|
1776
|
+
currentUrl,
|
|
1777
|
+
appContext,
|
|
1778
|
+
buyPath
|
|
1459
1779
|
});
|
|
1460
|
-
|
|
1780
|
+
const ga4Attributes = getGA4Attributes(ga4Data);
|
|
1781
|
+
return [...basicAttributes, ...ga4Attributes];
|
|
1782
|
+
}, [profile, customer, cart, memberType, currentUrl, appContext, buyPath, ga4Data]);
|
|
1461
1783
|
return react.useMemo(
|
|
1462
1784
|
() => ({
|
|
1463
1785
|
attributes
|
|
@@ -1520,12 +1842,9 @@ var useUpdateLineCodeAmountAttributes = ({
|
|
|
1520
1842
|
const codeDiscount = line.discountAllocations?.find(
|
|
1521
1843
|
(allocation) => mainProductDiscountCodes?.includes(allocation.code)
|
|
1522
1844
|
);
|
|
1523
|
-
const hasFunctionEnvAttribute = line.customAttributes?.find(
|
|
1524
|
-
(attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY
|
|
1525
|
-
);
|
|
1526
1845
|
const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
|
|
1527
1846
|
const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
|
|
1528
|
-
if (!hasSameFunctionEnvAttribute &&
|
|
1847
|
+
if (!hasSameFunctionEnvAttribute && !functionEnvValue.is_gift) {
|
|
1529
1848
|
attrNeedUpdate.push({
|
|
1530
1849
|
key: CUSTOMER_ATTRIBUTE_KEY,
|
|
1531
1850
|
value: JSON.stringify({
|
|
@@ -1946,47 +2265,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
|
|
|
1946
2265
|
return checkoutCustomAttributes;
|
|
1947
2266
|
}, [profile, selectedShippingMethod, selectedPlusMemberMode, isPresaleContains]);
|
|
1948
2267
|
};
|
|
1949
|
-
function useRemoveCartLines(options) {
|
|
1950
|
-
const { client, locale, cartCookieAdapter } = useShopify();
|
|
1951
|
-
const { mutateCart, metafieldIdentifiers } = useCartContext();
|
|
1952
|
-
const removeLines = react.useCallback(
|
|
1953
|
-
async (_key, { arg }) => {
|
|
1954
|
-
const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
|
|
1955
|
-
let updatedCart = await shopifySdk.removeCartLines(client, {
|
|
1956
|
-
cartId,
|
|
1957
|
-
lineIds,
|
|
1958
|
-
metafieldIdentifiers,
|
|
1959
|
-
cookieAdapter: cartCookieAdapter
|
|
1960
|
-
});
|
|
1961
|
-
if (updatedCart && autoRemoveInvalidCodes) {
|
|
1962
|
-
const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
|
|
1963
|
-
if (unApplicableCodes.length > 0) {
|
|
1964
|
-
if (onCodesRemoved) {
|
|
1965
|
-
const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
|
|
1966
|
-
if (handledCart) {
|
|
1967
|
-
updatedCart = handledCart;
|
|
1968
|
-
}
|
|
1969
|
-
} else {
|
|
1970
|
-
updatedCart = await shopifySdk.updateCartCodes(client, {
|
|
1971
|
-
cartId: updatedCart.id,
|
|
1972
|
-
discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
|
|
1973
|
-
metafieldIdentifiers,
|
|
1974
|
-
cookieAdapter: cartCookieAdapter
|
|
1975
|
-
}) || updatedCart;
|
|
1976
|
-
}
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
if (updatedCart) {
|
|
1980
|
-
mutateCart(updatedCart);
|
|
1981
|
-
}
|
|
1982
|
-
return updatedCart;
|
|
1983
|
-
},
|
|
1984
|
-
[client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
|
|
1985
|
-
);
|
|
1986
|
-
return useSWRMutation__default.default("remove-cart-lines", removeLines, options);
|
|
1987
|
-
}
|
|
1988
|
-
|
|
1989
|
-
// src/hooks/member/plus/use-auto-remove-plus-member-in-cart.ts
|
|
1990
2268
|
function useAutoRemovePlusMemberInCart({
|
|
1991
2269
|
cart,
|
|
1992
2270
|
profile,
|
|
@@ -2201,7 +2479,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
|
|
|
2201
2479
|
profile,
|
|
2202
2480
|
customer,
|
|
2203
2481
|
cart,
|
|
2204
|
-
memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
|
|
2482
|
+
memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0),
|
|
2483
|
+
buyPath: "hasCart"
|
|
2205
2484
|
});
|
|
2206
2485
|
const addToCart = react.useCallback(
|
|
2207
2486
|
async (_key, { arg }) => {
|
|
@@ -2294,7 +2573,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
|
|
|
2294
2573
|
applyCartCodes,
|
|
2295
2574
|
removeInvalidCodes,
|
|
2296
2575
|
addCustomAttributes,
|
|
2297
|
-
config
|
|
2576
|
+
config,
|
|
2577
|
+
cartAttributes
|
|
2298
2578
|
]
|
|
2299
2579
|
);
|
|
2300
2580
|
return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
|
|
@@ -2373,7 +2653,7 @@ function useUpdateBuyerIdentity({
|
|
|
2373
2653
|
}
|
|
2374
2654
|
function useBuyNow({ withTrack = true } = {}, swrOptions) {
|
|
2375
2655
|
const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
|
|
2376
|
-
const { profile, customer, memberSetting } = useCartContext();
|
|
2656
|
+
const { profile, customer, memberSetting, appContext } = useCartContext();
|
|
2377
2657
|
const isLoggedIn = userAdapter?.isLoggedIn || false;
|
|
2378
2658
|
const buyNow = react.useCallback(
|
|
2379
2659
|
async (_key, { arg }) => {
|
|
@@ -2395,12 +2675,6 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
|
|
|
2395
2675
|
lines: lineItems
|
|
2396
2676
|
});
|
|
2397
2677
|
const memberType = hasPlusMember ? "2" : String(profile?.memberType ?? 0);
|
|
2398
|
-
const cartAttributes = getCartAttributes({
|
|
2399
|
-
profile,
|
|
2400
|
-
customer,
|
|
2401
|
-
memberType,
|
|
2402
|
-
currentUrl: window.location.href
|
|
2403
|
-
});
|
|
2404
2678
|
const linesWithFunctionAttributes = getLinesWithAttributes({
|
|
2405
2679
|
lineItems
|
|
2406
2680
|
});
|
|
@@ -2413,13 +2687,23 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
|
|
|
2413
2687
|
if (lines.length === 0) {
|
|
2414
2688
|
return;
|
|
2415
2689
|
}
|
|
2690
|
+
const basicCartAttributes = getCartBasicAttributes({
|
|
2691
|
+
profile,
|
|
2692
|
+
customer,
|
|
2693
|
+
memberType,
|
|
2694
|
+
cart: { lineItems },
|
|
2695
|
+
currentUrl: window.location.href,
|
|
2696
|
+
appContext,
|
|
2697
|
+
buyPath: "buyNow"
|
|
2698
|
+
});
|
|
2699
|
+
const ga4Attributes = await getGA4AttributesAsync();
|
|
2416
2700
|
const resultCart = await shopifySdk.createCart(client, {
|
|
2417
2701
|
lines,
|
|
2418
2702
|
metafieldIdentifiers,
|
|
2419
2703
|
cookieAdapter: cartCookieAdapter,
|
|
2420
2704
|
buyerIdentity,
|
|
2421
2705
|
discountCodes,
|
|
2422
|
-
customAttributes: [...
|
|
2706
|
+
customAttributes: [...basicCartAttributes, ...ga4Attributes, ...customAttributes || []]
|
|
2423
2707
|
});
|
|
2424
2708
|
if (!resultCart) {
|
|
2425
2709
|
throw new Error("Failed to create cart for buy now");
|
|
@@ -2444,7 +2728,17 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
|
|
|
2444
2728
|
}
|
|
2445
2729
|
return resultCart;
|
|
2446
2730
|
},
|
|
2447
|
-
[
|
|
2731
|
+
[
|
|
2732
|
+
client,
|
|
2733
|
+
locale,
|
|
2734
|
+
isLoggedIn,
|
|
2735
|
+
cartCookieAdapter,
|
|
2736
|
+
withTrack,
|
|
2737
|
+
customer,
|
|
2738
|
+
profile,
|
|
2739
|
+
memberSetting,
|
|
2740
|
+
appContext
|
|
2741
|
+
]
|
|
2448
2742
|
);
|
|
2449
2743
|
return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
|
|
2450
2744
|
}
|
|
@@ -3240,13 +3534,14 @@ var CartContext = react.createContext(null);
|
|
|
3240
3534
|
function CartProvider({
|
|
3241
3535
|
children,
|
|
3242
3536
|
// swrOptions,
|
|
3243
|
-
|
|
3244
|
-
|
|
3537
|
+
functionAutoFreeGiftConfig,
|
|
3538
|
+
scriptAutoFreeGiftConfig,
|
|
3245
3539
|
profile,
|
|
3246
3540
|
customer,
|
|
3247
3541
|
locale,
|
|
3248
3542
|
metafieldIdentifiers,
|
|
3249
|
-
memberSetting
|
|
3543
|
+
memberSetting,
|
|
3544
|
+
appContext
|
|
3250
3545
|
}) {
|
|
3251
3546
|
const { client, cartCookieAdapter } = useShopify();
|
|
3252
3547
|
const [customAttributes, setCustomAttributes] = react.useState([]);
|
|
@@ -3291,7 +3586,8 @@ function CartProvider({
|
|
|
3291
3586
|
profile,
|
|
3292
3587
|
customer,
|
|
3293
3588
|
cart,
|
|
3294
|
-
memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
|
|
3589
|
+
memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0),
|
|
3590
|
+
appContext
|
|
3295
3591
|
});
|
|
3296
3592
|
ahooks.useRequest(
|
|
3297
3593
|
() => {
|
|
@@ -3345,9 +3641,13 @@ function CartProvider({
|
|
|
3345
3641
|
},
|
|
3346
3642
|
[setCustomAttributes]
|
|
3347
3643
|
);
|
|
3348
|
-
const functionAutoFreeGiftResult = useCalcAutoFreeGift(
|
|
3644
|
+
const functionAutoFreeGiftResult = useCalcAutoFreeGift(
|
|
3645
|
+
cart,
|
|
3646
|
+
functionAutoFreeGiftConfig || [],
|
|
3647
|
+
customer
|
|
3648
|
+
);
|
|
3349
3649
|
const scriptAutoFreeGiftResult = useScriptAutoFreeGift({
|
|
3350
|
-
campaign:
|
|
3650
|
+
campaign: scriptAutoFreeGiftConfig,
|
|
3351
3651
|
_giveaway: CUSTOMER_SCRIPT_GIFT_KEY,
|
|
3352
3652
|
cart,
|
|
3353
3653
|
profile
|
|
@@ -3355,10 +3655,10 @@ function CartProvider({
|
|
|
3355
3655
|
const formattedScriptGifts = react.useMemo(() => {
|
|
3356
3656
|
return formatScriptAutoFreeGift({
|
|
3357
3657
|
scriptAutoFreeGiftResult,
|
|
3358
|
-
gradient_gifts:
|
|
3658
|
+
gradient_gifts: scriptAutoFreeGiftConfig,
|
|
3359
3659
|
locale
|
|
3360
3660
|
});
|
|
3361
|
-
}, [scriptAutoFreeGiftResult,
|
|
3661
|
+
}, [scriptAutoFreeGiftResult, scriptAutoFreeGiftConfig, locale]);
|
|
3362
3662
|
const formattedFunctionGifts = react.useMemo(() => {
|
|
3363
3663
|
return formatFunctionAutoFreeGift({
|
|
3364
3664
|
qualifyingGift: functionAutoFreeGiftResult?.qualifyingGift || null,
|
|
@@ -3406,6 +3706,12 @@ function CartProvider({
|
|
|
3406
3706
|
const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
|
|
3407
3707
|
return cartLinesCount + giftLinesCount;
|
|
3408
3708
|
}, [cart?.lineItems, giftNeedAddToCartLines]);
|
|
3709
|
+
const autoRemoveFreeGiftsOptions = react.useMemo(() => {
|
|
3710
|
+
return {
|
|
3711
|
+
removeFunctionGifts: !!functionAutoFreeGiftConfig,
|
|
3712
|
+
removeScriptGifts: !!scriptAutoFreeGiftConfig
|
|
3713
|
+
};
|
|
3714
|
+
}, [functionAutoFreeGiftConfig, scriptAutoFreeGiftConfig]);
|
|
3409
3715
|
const value = react.useMemo(
|
|
3410
3716
|
() => ({
|
|
3411
3717
|
totalQuantity,
|
|
@@ -3420,8 +3726,8 @@ function CartProvider({
|
|
|
3420
3726
|
customer,
|
|
3421
3727
|
isCodeChanging,
|
|
3422
3728
|
setIsCodeChanging,
|
|
3423
|
-
|
|
3424
|
-
|
|
3729
|
+
functionAutoFreeGiftConfig,
|
|
3730
|
+
scriptAutoFreeGiftConfig,
|
|
3425
3731
|
setLoadingState,
|
|
3426
3732
|
loadingState,
|
|
3427
3733
|
// function满赠
|
|
@@ -3434,7 +3740,9 @@ function CartProvider({
|
|
|
3434
3740
|
setScriptAutoFreeGift,
|
|
3435
3741
|
giftNeedAddToCartLines,
|
|
3436
3742
|
metafieldIdentifiers,
|
|
3437
|
-
memberSetting
|
|
3743
|
+
memberSetting,
|
|
3744
|
+
appContext,
|
|
3745
|
+
autoRemoveFreeGiftsOptions
|
|
3438
3746
|
}),
|
|
3439
3747
|
[
|
|
3440
3748
|
cart,
|
|
@@ -3446,8 +3754,8 @@ function CartProvider({
|
|
|
3446
3754
|
removeCustomAttributes,
|
|
3447
3755
|
locale,
|
|
3448
3756
|
isCodeChanging,
|
|
3449
|
-
|
|
3450
|
-
|
|
3757
|
+
functionAutoFreeGiftConfig,
|
|
3758
|
+
scriptAutoFreeGiftConfig,
|
|
3451
3759
|
loadingState,
|
|
3452
3760
|
// function满赠
|
|
3453
3761
|
functionAutoFreeGift,
|
|
@@ -3461,7 +3769,9 @@ function CartProvider({
|
|
|
3461
3769
|
metafieldIdentifiers,
|
|
3462
3770
|
customer,
|
|
3463
3771
|
profile,
|
|
3464
|
-
memberSetting
|
|
3772
|
+
memberSetting,
|
|
3773
|
+
appContext,
|
|
3774
|
+
autoRemoveFreeGiftsOptions
|
|
3465
3775
|
]
|
|
3466
3776
|
);
|
|
3467
3777
|
return /* @__PURE__ */ jsxRuntime.jsx(CartContext.Provider, { value, children });
|
|
@@ -3507,14 +3817,24 @@ exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
|
|
|
3507
3817
|
exports.formatScriptAutoFreeGift = formatScriptAutoFreeGift;
|
|
3508
3818
|
exports.gaTrack = gaTrack;
|
|
3509
3819
|
exports.getCachedGeoLocation = getCachedGeoLocation;
|
|
3510
|
-
exports.
|
|
3820
|
+
exports.getCartBasicAttributes = getCartBasicAttributes;
|
|
3511
3821
|
exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
|
|
3822
|
+
exports.getGA4Attributes = getGA4Attributes;
|
|
3823
|
+
exports.getGA4AttributesAsync = getGA4AttributesAsync;
|
|
3824
|
+
exports.getGA4ClientId = getGA4ClientId;
|
|
3825
|
+
exports.getGA4Data = getGA4Data;
|
|
3826
|
+
exports.getGA4SessionId = getGA4SessionId;
|
|
3512
3827
|
exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
|
|
3828
|
+
exports.getOperatingSystem = getOperatingSystem;
|
|
3513
3829
|
exports.getQuery = getQuery;
|
|
3514
3830
|
exports.getReferralAttributes = getReferralAttributes;
|
|
3515
3831
|
exports.getUserType = getUserType;
|
|
3516
3832
|
exports.hasPlusMemberInCart = hasPlusMemberInCart;
|
|
3517
3833
|
exports.hasPlusMemberInLines = hasPlusMemberInLines;
|
|
3834
|
+
exports.isAnyGift = isAnyGift;
|
|
3835
|
+
exports.isBuyGetGift = isBuyGetGift;
|
|
3836
|
+
exports.isFunctionGift = isFunctionGift;
|
|
3837
|
+
exports.isScriptGift = isScriptGift;
|
|
3518
3838
|
exports.normalizeAddToCartLines = normalizeAddToCartLines;
|
|
3519
3839
|
exports.preCheck = preCheck;
|
|
3520
3840
|
exports.safeParse = safeParse;
|
|
@@ -3532,6 +3852,7 @@ exports.useApplyCartCodes = useApplyCartCodes;
|
|
|
3532
3852
|
exports.useArticle = useArticle;
|
|
3533
3853
|
exports.useArticles = useArticles;
|
|
3534
3854
|
exports.useArticlesInBlog = useArticlesInBlog;
|
|
3855
|
+
exports.useAutoRemoveFreeGifts = useAutoRemoveFreeGifts;
|
|
3535
3856
|
exports.useAutoRemovePlusMemberInCart = useAutoRemovePlusMemberInCart;
|
|
3536
3857
|
exports.useAvailableDeliveryCoupon = useAvailableDeliveryCoupon;
|
|
3537
3858
|
exports.useBlog = useBlog;
|
|
@@ -3574,6 +3895,7 @@ exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
|
|
|
3574
3895
|
exports.useUpdateVariantQuery = useUpdateVariantQuery;
|
|
3575
3896
|
exports.useVariant = useVariant;
|
|
3576
3897
|
exports.useVariantMedia = useVariantMedia;
|
|
3898
|
+
exports.waitForGtagReady = waitForGtagReady;
|
|
3577
3899
|
Object.keys(shopifySdk).forEach(function (k) {
|
|
3578
3900
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
3579
3901
|
enumerable: true,
|