@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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createContext, useMemo, useContext, useRef, useState, useEffect, useCallback } from 'react';
2
- import { createShopifyClient, getProductsByHandles, createCart, updateCartCodes, addCartLines, getLocalStorage, updateCartLines, removeCartLines, updateCartAttributes, updateBuyerIdentity, getProduct, getAllProducts, getCollection, getAllCollections, getCollections, getBlog, getAllBlogs, getArticle, getArticles, getArticlesInBlog, getCart, setLocalStorage } from '@anker-in/shopify-sdk';
2
+ import { createShopifyClient, getProductsByHandles, createCart, updateCartCodes, addCartLines, removeCartLines, getLocalStorage, updateCartLines, updateCartAttributes, updateBuyerIdentity, getProduct, getAllProducts, getCollection, getAllCollections, getCollections, getBlog, getAllBlogs, getArticle, getArticles, getArticlesInBlog, getCart, setLocalStorage } from '@anker-in/shopify-sdk';
3
3
  export * from '@anker-in/shopify-sdk';
4
4
  import Cookies5 from 'js-cookie';
5
5
  import { jsx } from 'react/jsx-runtime';
@@ -877,15 +877,23 @@ var trackAddToCartGA = ({
877
877
  currency: currencyCode,
878
878
  value: totalPrice,
879
879
  position: gtmParams?.position || "",
880
- items: lineItems.map(({ variant: variant2, quantity }) => ({
881
- item_id: variant2?.sku,
882
- item_name: variant2?.product?.title || variant2?.product?.title,
883
- item_brand: gtmParams?.brand || "",
884
- item_category: variant2?.product?.productType || "",
885
- item_variant: variant2?.title || variant2?.title,
886
- price: variant2?.compareAtPrice?.amount ?? variant2?.price?.amount,
887
- quantity: quantity || 1
888
- })),
880
+ items: lineItems.map((item) => {
881
+ const imageUrl = item.variant?.image?.url || item.variant?.product?.images?.[0]?.url;
882
+ const itemCategoryId = item.gtmParams?.item_category_id;
883
+ const itemVariantId = item.variant?.id ? atobID(item.variant.id) : void 0;
884
+ return {
885
+ item_id: item.variant?.sku,
886
+ item_name: item.variant?.product?.title || item.variant?.product?.title,
887
+ item_brand: gtmParams?.brand || "",
888
+ item_category: item.variant?.product?.productType || "",
889
+ item_variant: item.variant?.title || item.variant?.title,
890
+ price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
891
+ quantity: item.quantity || 1,
892
+ ...imageUrl && { image_url: imageUrl },
893
+ ...itemCategoryId && { item_category_id: itemCategoryId },
894
+ ...itemVariantId && { item_variant_id: itemVariantId }
895
+ };
896
+ }),
889
897
  ...gtmParams?.ga4Params
890
898
  }
891
899
  });
@@ -912,15 +920,23 @@ var trackBeginCheckoutGA = ({
912
920
  position: gtmParams?.position,
913
921
  currency: currencyCode,
914
922
  value: totalPrice,
915
- items: lineItems.map((item) => ({
916
- item_id: item.variant?.sku,
917
- item_name: item.variant?.product?.title,
918
- item_brand: gtmParams?.brand || "",
919
- item_category: item.variant?.product?.productType,
920
- item_variant: item.variant?.title,
921
- price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
922
- quantity: item.quantity || 1
923
- })),
923
+ items: lineItems.map((item) => {
924
+ const imageUrl = item.variant?.image?.url || item.variant?.product?.images?.[0]?.url;
925
+ const itemCategoryId = item.gtmParams?.item_category_id;
926
+ const itemVariantId = item.variant?.id ? atobID(item.variant.id) : void 0;
927
+ return {
928
+ item_id: item.variant?.sku,
929
+ item_name: item.variant?.product?.title,
930
+ item_brand: gtmParams?.brand || "",
931
+ item_category: item.variant?.product?.productType,
932
+ item_variant: item.variant?.title,
933
+ price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
934
+ quantity: item.quantity || 1,
935
+ ...imageUrl && { image_url: imageUrl },
936
+ ...itemCategoryId !== void 0 && { item_category_id: itemCategoryId },
937
+ ...itemVariantId && { item_variant_id: itemVariantId }
938
+ };
939
+ }),
924
940
  ...gtmParams?.ga4Params
925
941
  }
926
942
  });
@@ -948,19 +964,111 @@ var trackBuyNowGA = ({
948
964
  position: gtmParams?.position,
949
965
  currency: currencyCode,
950
966
  value: totalPrice,
951
- items: lineItems.map((item) => ({
952
- item_id: item.variant?.sku,
953
- item_name: item.variant?.product?.title || item.variant?.title,
954
- item_brand: gtmParams?.brand || "",
955
- item_category: item.variant?.product?.productType || "",
956
- item_variant: item.variant?.title,
957
- price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
958
- quantity: item.quantity || 1
959
- })),
967
+ items: lineItems.map((item) => {
968
+ const imageUrl = item.variant?.image?.url || item.variant?.product?.images?.[0]?.url;
969
+ const itemCategoryId = item.gtmParams?.item_category_id;
970
+ const itemVariantId = item.variant?.id ? atobID(item.variant.id) : void 0;
971
+ return {
972
+ item_id: item.variant?.sku,
973
+ item_name: item.variant?.product?.title || item.variant?.title,
974
+ item_brand: gtmParams?.brand || "",
975
+ item_category: item.variant?.product?.productType || "",
976
+ item_variant: item.variant?.title,
977
+ price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
978
+ quantity: item.quantity || 1,
979
+ ...imageUrl && { image_url: imageUrl },
980
+ ...itemCategoryId !== void 0 && { item_category_id: itemCategoryId },
981
+ ...itemVariantId && { item_variant_id: itemVariantId }
982
+ };
983
+ }),
960
984
  ...gtmParams?.ga4Params
961
985
  }
962
986
  });
963
987
  };
988
+ function waitForGtagReady(timeout = 1e4) {
989
+ return new Promise((resolve, reject) => {
990
+ const start = Date.now();
991
+ function check() {
992
+ if (typeof window !== "undefined" && typeof window.gtag !== "undefined") {
993
+ resolve();
994
+ } else if (Date.now() - start > timeout) {
995
+ reject(new Error("GA4 gtag not loaded"));
996
+ } else {
997
+ setTimeout(check, 50);
998
+ }
999
+ }
1000
+ check();
1001
+ });
1002
+ }
1003
+ var getGA4ClientId = async (measurementId = "G-R0BRMRK4CY") => {
1004
+ try {
1005
+ await waitForGtagReady();
1006
+ return new Promise((resolve, reject) => {
1007
+ if (!window.gtag) {
1008
+ reject(new Error("gtag is not defined"));
1009
+ return;
1010
+ }
1011
+ window.gtag("get", measurementId, "client_id", (clientId) => {
1012
+ if (clientId) {
1013
+ resolve(clientId);
1014
+ } else {
1015
+ reject(new Error("Failed to get client_id"));
1016
+ }
1017
+ });
1018
+ });
1019
+ } catch (error) {
1020
+ console.error("Failed to get GA4 client_id:", error);
1021
+ return "";
1022
+ }
1023
+ };
1024
+ var getGA4SessionId = async (measurementId = "G-R0BRMRK4CY") => {
1025
+ try {
1026
+ await waitForGtagReady();
1027
+ return new Promise((resolve) => {
1028
+ if (!window.gtag) {
1029
+ resolve("");
1030
+ return;
1031
+ }
1032
+ window.gtag("get", measurementId, "session_id", (sessionId) => {
1033
+ resolve(sessionId || "");
1034
+ });
1035
+ });
1036
+ } catch (error) {
1037
+ console.error("Failed to get GA4 session_id:", error);
1038
+ return "";
1039
+ }
1040
+ };
1041
+ var getGA4Data = async (measurementId = "G-R0BRMRK4CY") => {
1042
+ try {
1043
+ await waitForGtagReady();
1044
+ const timeoutPromise = new Promise((resolve) => {
1045
+ setTimeout(() => {
1046
+ resolve({ clientId: "", sessionId: "" });
1047
+ }, 300);
1048
+ });
1049
+ const dataPromise = new Promise((resolve) => {
1050
+ if (!window.gtag) {
1051
+ resolve({ clientId: "", sessionId: "" });
1052
+ return;
1053
+ }
1054
+ window.gtag("get", measurementId, "client_id", (clientId) => {
1055
+ window.gtag("get", measurementId, "session_id", (sessionId) => {
1056
+ resolve({
1057
+ clientId: clientId || "",
1058
+ sessionId: sessionId || ""
1059
+ });
1060
+ });
1061
+ });
1062
+ });
1063
+ return Promise.race([dataPromise, timeoutPromise]);
1064
+ } catch (error) {
1065
+ console.error("Failed to get GA4 data:", error);
1066
+ return {
1067
+ clientId: "",
1068
+ sessionId: ""
1069
+ };
1070
+ }
1071
+ };
964
1072
 
965
1073
  // src/tracking/fbq.ts
966
1074
  var trackAddToCartFBQ = ({ lineItems = [] }) => {
@@ -1143,16 +1251,155 @@ var getLinesWithAttributes = ({
1143
1251
  return functionLine;
1144
1252
  });
1145
1253
  };
1254
+ function useRemoveCartLines(options) {
1255
+ const { client, locale, cartCookieAdapter } = useShopify();
1256
+ const { mutateCart, metafieldIdentifiers } = useCartContext();
1257
+ const removeLines = useCallback(
1258
+ async (_key, { arg }) => {
1259
+ const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
1260
+ let updatedCart = await removeCartLines(client, {
1261
+ cartId,
1262
+ lineIds,
1263
+ metafieldIdentifiers,
1264
+ cookieAdapter: cartCookieAdapter
1265
+ });
1266
+ if (updatedCart && autoRemoveInvalidCodes) {
1267
+ const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
1268
+ if (unApplicableCodes.length > 0) {
1269
+ if (onCodesRemoved) {
1270
+ const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
1271
+ if (handledCart) {
1272
+ updatedCart = handledCart;
1273
+ }
1274
+ } else {
1275
+ updatedCart = await updateCartCodes(client, {
1276
+ cartId: updatedCart.id,
1277
+ discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
1278
+ metafieldIdentifiers,
1279
+ cookieAdapter: cartCookieAdapter
1280
+ }) || updatedCart;
1281
+ }
1282
+ }
1283
+ }
1284
+ if (updatedCart) {
1285
+ mutateCart(updatedCart);
1286
+ }
1287
+ return updatedCart;
1288
+ },
1289
+ [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1290
+ );
1291
+ return useSWRMutation("remove-cart-lines", removeLines, options);
1292
+ }
1293
+
1294
+ // src/hooks/cart/feature/use-auto-remove-free-gifts.ts
1295
+ function useAutoRemoveFreeGifts(options = {}) {
1296
+ const {
1297
+ removeFunctionGifts = true,
1298
+ removeScriptGifts = true,
1299
+ isGiftLineItem
1300
+ } = options;
1301
+ const [isRemoving, setIsRemoving] = useState(false);
1302
+ const { cart } = useCartContext();
1303
+ const { trigger: removeCartLines2 } = useRemoveCartLines();
1304
+ const giftsToRemove = useMemo(() => {
1305
+ if (!cart?.lineItems) {
1306
+ return [];
1307
+ }
1308
+ return cart.lineItems.filter((item) => {
1309
+ if (removeFunctionGifts) {
1310
+ const functionAttr = item.customAttributes?.find(
1311
+ (attr) => attr.key === "_discounts_function_env"
1312
+ )?.value;
1313
+ if (functionAttr) {
1314
+ try {
1315
+ const functionAttrObj = JSON.parse(functionAttr);
1316
+ if (functionAttrObj.is_gift && functionAttrObj.rule_id && functionAttrObj.spend_sum_money) {
1317
+ return true;
1318
+ }
1319
+ } catch (error) {
1320
+ console.error("Failed to parse _discounts_function_env:", error);
1321
+ }
1322
+ }
1323
+ }
1324
+ if (removeScriptGifts) {
1325
+ const scriptGiftAttr = item.customAttributes?.find(
1326
+ (attr) => attr.key === "_giveaway_gradient_gifts"
1327
+ );
1328
+ if (scriptGiftAttr) {
1329
+ return true;
1330
+ }
1331
+ }
1332
+ if (isGiftLineItem && isGiftLineItem(item)) {
1333
+ return true;
1334
+ }
1335
+ return false;
1336
+ });
1337
+ }, [cart, removeFunctionGifts, removeScriptGifts, isGiftLineItem]);
1338
+ useEffect(() => {
1339
+ if (isRemoving || giftsToRemove.length === 0) {
1340
+ return;
1341
+ }
1342
+ const performRemoval = async () => {
1343
+ setIsRemoving(true);
1344
+ try {
1345
+ await removeCartLines2({
1346
+ lineIds: giftsToRemove.map((item) => item.id)
1347
+ });
1348
+ } catch (error) {
1349
+ console.error("Failed to remove free gifts:", error);
1350
+ } finally {
1351
+ setIsRemoving(false);
1352
+ }
1353
+ };
1354
+ performRemoval();
1355
+ }, [
1356
+ isRemoving,
1357
+ giftsToRemove,
1358
+ removeCartLines2
1359
+ ]);
1360
+ return {
1361
+ isRemoving
1362
+ };
1363
+ }
1364
+ function isFunctionGift(line) {
1365
+ const functionAttr = line.customAttributes?.find(
1366
+ (attr) => attr.key === "_discounts_function_env"
1367
+ )?.value;
1368
+ if (!functionAttr) {
1369
+ return false;
1370
+ }
1371
+ try {
1372
+ const functionAttrObj = JSON.parse(functionAttr);
1373
+ return Boolean(
1374
+ functionAttrObj.is_gift && functionAttrObj.rule_id && functionAttrObj.spend_sum_money
1375
+ );
1376
+ } catch {
1377
+ return false;
1378
+ }
1379
+ }
1380
+ function isScriptGift(line) {
1381
+ return line.customAttributes?.some(
1382
+ (attr) => attr.key === "_giveaway_gradient_gifts"
1383
+ ) ?? false;
1384
+ }
1385
+ function isBuyGetGift(line) {
1386
+ return line.customAttributes?.some(
1387
+ (attr) => attr.key === "_freegift_related_handlesku"
1388
+ ) ?? false;
1389
+ }
1390
+ function isAnyGift(line) {
1391
+ return isFunctionGift(line) || isScriptGift(line) || isBuyGetGift(line);
1392
+ }
1146
1393
  function useCalcGiftsFromLines({
1147
1394
  lines,
1148
1395
  customer,
1149
1396
  scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1150
1397
  }) {
1151
1398
  const { locale } = useShopify();
1152
- const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1153
- const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1399
+ const { cart, functionAutoFreeGiftConfig, scriptAutoFreeGiftConfig } = useCartContext();
1400
+ const functionGift = useCalcAutoFreeGift(cart, functionAutoFreeGiftConfig || [], customer, lines);
1154
1401
  const scriptGift = useScriptAutoFreeGift({
1155
- campaign: gradientGiftsConfig || null,
1402
+ campaign: scriptAutoFreeGiftConfig,
1156
1403
  _giveaway: scriptGiveawayKey,
1157
1404
  cart,
1158
1405
  locale,
@@ -1187,7 +1434,9 @@ function useCalcGiftsFromLines({
1187
1434
  const variants = product?.variants;
1188
1435
  const variant = Array.isArray(variants) ? variants.find((v) => v.sku === item.sku) : void 0;
1189
1436
  if (!variant) {
1190
- console.warn(`Script gift: Variant not found for handle=${item.handle}, sku=${item.sku}`);
1437
+ console.warn(
1438
+ `Script gift: Variant not found for handle=${item.handle}, sku=${item.sku}`
1439
+ );
1191
1440
  return null;
1192
1441
  }
1193
1442
  return {
@@ -1330,6 +1579,19 @@ var getReferralAttributes = () => {
1330
1579
  }
1331
1580
  return [];
1332
1581
  };
1582
+ var getOperatingSystem = () => {
1583
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
1584
+ return "Unknown";
1585
+ }
1586
+ const userAgent = navigator.userAgent || navigator.vendor || window.opera;
1587
+ if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
1588
+ return "IOS";
1589
+ }
1590
+ if (/android/i.test(userAgent)) {
1591
+ return "Android";
1592
+ }
1593
+ return "Unknown";
1594
+ };
1333
1595
  var getUserType = (customer) => {
1334
1596
  let userInfo = Cookies5.get("userInfo");
1335
1597
  if (userInfo) {
@@ -1351,12 +1613,42 @@ var getUserType = (customer) => {
1351
1613
  }
1352
1614
  return "new_user_login";
1353
1615
  };
1354
- function getCartAttributes({
1616
+ function getGA4Attributes(ga4Data) {
1617
+ if (!ga4Data?.clientId && !ga4Data?.sessionId) {
1618
+ return [];
1619
+ }
1620
+ const attributes = [];
1621
+ if (ga4Data.clientId) {
1622
+ attributes.push({
1623
+ key: "_ga4_client_id",
1624
+ value: ga4Data.clientId
1625
+ });
1626
+ }
1627
+ if (ga4Data.sessionId) {
1628
+ attributes.push({
1629
+ key: "_ga4_session_id",
1630
+ value: ga4Data.sessionId
1631
+ });
1632
+ }
1633
+ return attributes;
1634
+ }
1635
+ async function getGA4AttributesAsync() {
1636
+ try {
1637
+ const ga4Data = await getGA4Data();
1638
+ return getGA4Attributes(ga4Data);
1639
+ } catch (error) {
1640
+ console.error("Failed to get GA4 attributes:", error);
1641
+ return [];
1642
+ }
1643
+ }
1644
+ function getCartBasicAttributes({
1355
1645
  profile,
1356
1646
  customer,
1357
1647
  cart,
1358
1648
  memberType,
1359
- currentUrl = ""
1649
+ currentUrl = "",
1650
+ appContext,
1651
+ buyPath
1360
1652
  }) {
1361
1653
  const userType = getUserType(customer);
1362
1654
  const memberAttributes = [
@@ -1383,12 +1675,10 @@ function getCartAttributes({
1383
1675
  value: "1"
1384
1676
  });
1385
1677
  }
1386
- const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1387
1678
  const functionAttributes = [
1388
1679
  {
1389
1680
  key: CUSTOMER_ATTRIBUTE_KEY,
1390
1681
  value: JSON.stringify({
1391
- discount_code: discountCodes,
1392
1682
  user_tags: customer?.tags || []
1393
1683
  })
1394
1684
  }
@@ -1396,26 +1686,38 @@ function getCartAttributes({
1396
1686
  const presellAttributes = [
1397
1687
  {
1398
1688
  key: "_presale",
1399
- value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
1689
+ value: cart?.lineItems?.some((item) => item?.variant?.metafields?.presell === "presell")
1400
1690
  }
1401
1691
  ];
1402
1692
  const weightAttributes = [
1403
1693
  {
1404
1694
  key: "_weight",
1405
- value: cart?.lineItems.reduce((acc, item) => {
1695
+ value: cart?.lineItems?.reduce((acc, item) => {
1406
1696
  const itemWeight = new Decimal2(item.variant.weight ?? 0).times(item.quantity);
1407
1697
  return new Decimal2(acc).plus(itemWeight).toNumber();
1408
1698
  }, 0).toString()
1409
- },
1410
- {
1411
- key: "_app_source_name",
1412
- value: "dtc"
1413
1699
  }
1414
1700
  ];
1415
1701
  const trackingAttributes = [
1416
1702
  {
1417
1703
  key: "utm_params",
1418
1704
  value: currentUrl
1705
+ },
1706
+ {
1707
+ key: "_app_source_name",
1708
+ value: appContext?.isInApp && appContext?.appName ? appContext.appName : "dtc"
1709
+ },
1710
+ {
1711
+ key: "_operating_system",
1712
+ value: getOperatingSystem()
1713
+ },
1714
+ {
1715
+ key: "_cart_id",
1716
+ value: cart?.id
1717
+ },
1718
+ {
1719
+ key: "_buy_path",
1720
+ value: buyPath
1419
1721
  }
1420
1722
  ];
1421
1723
  const commonAttributes = [
@@ -1435,21 +1737,41 @@ var useCartAttributes = ({
1435
1737
  profile,
1436
1738
  customer,
1437
1739
  cart,
1438
- memberType
1740
+ memberType,
1741
+ appContext,
1742
+ buyPath
1439
1743
  }) => {
1440
1744
  const [currentUrl, setCurrentUrl] = useState("");
1745
+ const [ga4Data, setGa4Data] = useState(null);
1441
1746
  useEffect(() => {
1442
1747
  setCurrentUrl(window.location.href);
1443
1748
  }, []);
1749
+ useEffect(() => {
1750
+ let isMounted = true;
1751
+ getGA4Data().then((data) => {
1752
+ if (isMounted) {
1753
+ setGa4Data(data);
1754
+ }
1755
+ }).catch((error) => {
1756
+ console.error("Failed to get GA4 data in useCartAttributes:", error);
1757
+ });
1758
+ return () => {
1759
+ isMounted = false;
1760
+ };
1761
+ }, []);
1444
1762
  const attributes = useMemo(() => {
1445
- return getCartAttributes({
1763
+ const basicAttributes = getCartBasicAttributes({
1446
1764
  profile,
1447
1765
  customer,
1448
1766
  cart,
1449
1767
  memberType,
1450
- currentUrl
1768
+ currentUrl,
1769
+ appContext,
1770
+ buyPath
1451
1771
  });
1452
- }, [profile, customer, cart, memberType, currentUrl]);
1772
+ const ga4Attributes = getGA4Attributes(ga4Data);
1773
+ return [...basicAttributes, ...ga4Attributes];
1774
+ }, [profile, customer, cart, memberType, currentUrl, appContext, buyPath, ga4Data]);
1453
1775
  return useMemo(
1454
1776
  () => ({
1455
1777
  attributes
@@ -1512,12 +1834,9 @@ var useUpdateLineCodeAmountAttributes = ({
1512
1834
  const codeDiscount = line.discountAllocations?.find(
1513
1835
  (allocation) => mainProductDiscountCodes?.includes(allocation.code)
1514
1836
  );
1515
- const hasFunctionEnvAttribute = line.customAttributes?.find(
1516
- (attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY
1517
- );
1518
1837
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
1519
1838
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
1520
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
1839
+ if (!hasSameFunctionEnvAttribute && !functionEnvValue.is_gift) {
1521
1840
  attrNeedUpdate.push({
1522
1841
  key: CUSTOMER_ATTRIBUTE_KEY,
1523
1842
  value: JSON.stringify({
@@ -1938,47 +2257,6 @@ var usePlusMemberCheckoutCustomAttributes = ({
1938
2257
  return checkoutCustomAttributes;
1939
2258
  }, [profile, selectedShippingMethod, selectedPlusMemberMode, isPresaleContains]);
1940
2259
  };
1941
- function useRemoveCartLines(options) {
1942
- const { client, locale, cartCookieAdapter } = useShopify();
1943
- const { mutateCart, metafieldIdentifiers } = useCartContext();
1944
- const removeLines = useCallback(
1945
- async (_key, { arg }) => {
1946
- const { autoRemoveInvalidCodes = true, onCodesRemoved, cartId, lineIds } = arg;
1947
- let updatedCart = await removeCartLines(client, {
1948
- cartId,
1949
- lineIds,
1950
- metafieldIdentifiers,
1951
- cookieAdapter: cartCookieAdapter
1952
- });
1953
- if (updatedCart && autoRemoveInvalidCodes) {
1954
- const unApplicableCodes = updatedCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
1955
- if (unApplicableCodes.length > 0) {
1956
- if (onCodesRemoved) {
1957
- const handledCart = await onCodesRemoved(updatedCart, unApplicableCodes);
1958
- if (handledCart) {
1959
- updatedCart = handledCart;
1960
- }
1961
- } else {
1962
- updatedCart = await updateCartCodes(client, {
1963
- cartId: updatedCart.id,
1964
- discountCodes: updatedCart.discountCodes.filter((item) => item.applicable).map((item) => item.code),
1965
- metafieldIdentifiers,
1966
- cookieAdapter: cartCookieAdapter
1967
- }) || updatedCart;
1968
- }
1969
- }
1970
- }
1971
- if (updatedCart) {
1972
- mutateCart(updatedCart);
1973
- }
1974
- return updatedCart;
1975
- },
1976
- [client, locale, cartCookieAdapter, mutateCart, metafieldIdentifiers]
1977
- );
1978
- return useSWRMutation("remove-cart-lines", removeLines, options);
1979
- }
1980
-
1981
- // src/hooks/member/plus/use-auto-remove-plus-member-in-cart.ts
1982
2260
  function useAutoRemovePlusMemberInCart({
1983
2261
  cart,
1984
2262
  profile,
@@ -2193,7 +2471,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
2193
2471
  profile,
2194
2472
  customer,
2195
2473
  cart,
2196
- memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
2474
+ memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0),
2475
+ buyPath: "hasCart"
2197
2476
  });
2198
2477
  const addToCart = useCallback(
2199
2478
  async (_key, { arg }) => {
@@ -2286,7 +2565,8 @@ function useAddToCart({ withTrack = true } = {}, swrOptions) {
2286
2565
  applyCartCodes,
2287
2566
  removeInvalidCodes,
2288
2567
  addCustomAttributes,
2289
- config
2568
+ config,
2569
+ cartAttributes
2290
2570
  ]
2291
2571
  );
2292
2572
  return useSWRMutation("add-to-cart", addToCart, swrOptions);
@@ -2365,7 +2645,7 @@ function useUpdateBuyerIdentity({
2365
2645
  }
2366
2646
  function useBuyNow({ withTrack = true } = {}, swrOptions) {
2367
2647
  const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
2368
- const { profile, customer, memberSetting } = useCartContext();
2648
+ const { profile, customer, memberSetting, appContext } = useCartContext();
2369
2649
  const isLoggedIn = userAdapter?.isLoggedIn || false;
2370
2650
  const buyNow = useCallback(
2371
2651
  async (_key, { arg }) => {
@@ -2387,12 +2667,6 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
2387
2667
  lines: lineItems
2388
2668
  });
2389
2669
  const memberType = hasPlusMember ? "2" : String(profile?.memberType ?? 0);
2390
- const cartAttributes = getCartAttributes({
2391
- profile,
2392
- customer,
2393
- memberType,
2394
- currentUrl: window.location.href
2395
- });
2396
2670
  const linesWithFunctionAttributes = getLinesWithAttributes({
2397
2671
  lineItems
2398
2672
  });
@@ -2405,13 +2679,23 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
2405
2679
  if (lines.length === 0) {
2406
2680
  return;
2407
2681
  }
2682
+ const basicCartAttributes = getCartBasicAttributes({
2683
+ profile,
2684
+ customer,
2685
+ memberType,
2686
+ cart: { lineItems },
2687
+ currentUrl: window.location.href,
2688
+ appContext,
2689
+ buyPath: "buyNow"
2690
+ });
2691
+ const ga4Attributes = await getGA4AttributesAsync();
2408
2692
  const resultCart = await createCart(client, {
2409
2693
  lines,
2410
2694
  metafieldIdentifiers,
2411
2695
  cookieAdapter: cartCookieAdapter,
2412
2696
  buyerIdentity,
2413
2697
  discountCodes,
2414
- customAttributes: [...cartAttributes, ...customAttributes || []]
2698
+ customAttributes: [...basicCartAttributes, ...ga4Attributes, ...customAttributes || []]
2415
2699
  });
2416
2700
  if (!resultCart) {
2417
2701
  throw new Error("Failed to create cart for buy now");
@@ -2436,7 +2720,17 @@ function useBuyNow({ withTrack = true } = {}, swrOptions) {
2436
2720
  }
2437
2721
  return resultCart;
2438
2722
  },
2439
- [client, locale, isLoggedIn, cartCookieAdapter, withTrack, customer, profile, memberSetting]
2723
+ [
2724
+ client,
2725
+ locale,
2726
+ isLoggedIn,
2727
+ cartCookieAdapter,
2728
+ withTrack,
2729
+ customer,
2730
+ profile,
2731
+ memberSetting,
2732
+ appContext
2733
+ ]
2440
2734
  );
2441
2735
  return useSWRMutation("buy-now", buyNow, swrOptions);
2442
2736
  }
@@ -3232,13 +3526,14 @@ var CartContext = createContext(null);
3232
3526
  function CartProvider({
3233
3527
  children,
3234
3528
  // swrOptions,
3235
- autoFreeGiftConfig,
3236
- gradientGiftsConfig,
3529
+ functionAutoFreeGiftConfig,
3530
+ scriptAutoFreeGiftConfig,
3237
3531
  profile,
3238
3532
  customer,
3239
3533
  locale,
3240
3534
  metafieldIdentifiers,
3241
- memberSetting
3535
+ memberSetting,
3536
+ appContext
3242
3537
  }) {
3243
3538
  const { client, cartCookieAdapter } = useShopify();
3244
3539
  const [customAttributes, setCustomAttributes] = useState([]);
@@ -3283,7 +3578,8 @@ function CartProvider({
3283
3578
  profile,
3284
3579
  customer,
3285
3580
  cart,
3286
- memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
3581
+ memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0),
3582
+ appContext
3287
3583
  });
3288
3584
  useRequest(
3289
3585
  () => {
@@ -3337,9 +3633,13 @@ function CartProvider({
3337
3633
  },
3338
3634
  [setCustomAttributes]
3339
3635
  );
3340
- const functionAutoFreeGiftResult = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer);
3636
+ const functionAutoFreeGiftResult = useCalcAutoFreeGift(
3637
+ cart,
3638
+ functionAutoFreeGiftConfig || [],
3639
+ customer
3640
+ );
3341
3641
  const scriptAutoFreeGiftResult = useScriptAutoFreeGift({
3342
- campaign: gradientGiftsConfig || null,
3642
+ campaign: scriptAutoFreeGiftConfig,
3343
3643
  _giveaway: CUSTOMER_SCRIPT_GIFT_KEY,
3344
3644
  cart,
3345
3645
  profile
@@ -3347,10 +3647,10 @@ function CartProvider({
3347
3647
  const formattedScriptGifts = useMemo(() => {
3348
3648
  return formatScriptAutoFreeGift({
3349
3649
  scriptAutoFreeGiftResult,
3350
- gradient_gifts: gradientGiftsConfig,
3650
+ gradient_gifts: scriptAutoFreeGiftConfig,
3351
3651
  locale
3352
3652
  });
3353
- }, [scriptAutoFreeGiftResult, gradientGiftsConfig, locale]);
3653
+ }, [scriptAutoFreeGiftResult, scriptAutoFreeGiftConfig, locale]);
3354
3654
  const formattedFunctionGifts = useMemo(() => {
3355
3655
  return formatFunctionAutoFreeGift({
3356
3656
  qualifyingGift: functionAutoFreeGiftResult?.qualifyingGift || null,
@@ -3398,6 +3698,12 @@ function CartProvider({
3398
3698
  const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
3399
3699
  return cartLinesCount + giftLinesCount;
3400
3700
  }, [cart?.lineItems, giftNeedAddToCartLines]);
3701
+ const autoRemoveFreeGiftsOptions = useMemo(() => {
3702
+ return {
3703
+ removeFunctionGifts: !!functionAutoFreeGiftConfig,
3704
+ removeScriptGifts: !!scriptAutoFreeGiftConfig
3705
+ };
3706
+ }, [functionAutoFreeGiftConfig, scriptAutoFreeGiftConfig]);
3401
3707
  const value = useMemo(
3402
3708
  () => ({
3403
3709
  totalQuantity,
@@ -3412,8 +3718,8 @@ function CartProvider({
3412
3718
  customer,
3413
3719
  isCodeChanging,
3414
3720
  setIsCodeChanging,
3415
- autoFreeGiftConfig,
3416
- gradientGiftsConfig,
3721
+ functionAutoFreeGiftConfig,
3722
+ scriptAutoFreeGiftConfig,
3417
3723
  setLoadingState,
3418
3724
  loadingState,
3419
3725
  // function满赠
@@ -3426,7 +3732,9 @@ function CartProvider({
3426
3732
  setScriptAutoFreeGift,
3427
3733
  giftNeedAddToCartLines,
3428
3734
  metafieldIdentifiers,
3429
- memberSetting
3735
+ memberSetting,
3736
+ appContext,
3737
+ autoRemoveFreeGiftsOptions
3430
3738
  }),
3431
3739
  [
3432
3740
  cart,
@@ -3438,8 +3746,8 @@ function CartProvider({
3438
3746
  removeCustomAttributes,
3439
3747
  locale,
3440
3748
  isCodeChanging,
3441
- autoFreeGiftConfig,
3442
- gradientGiftsConfig,
3749
+ functionAutoFreeGiftConfig,
3750
+ scriptAutoFreeGiftConfig,
3443
3751
  loadingState,
3444
3752
  // function满赠
3445
3753
  functionAutoFreeGift,
@@ -3453,7 +3761,9 @@ function CartProvider({
3453
3761
  metafieldIdentifiers,
3454
3762
  customer,
3455
3763
  profile,
3456
- memberSetting
3764
+ memberSetting,
3765
+ appContext,
3766
+ autoRemoveFreeGiftsOptions
3457
3767
  ]
3458
3768
  );
3459
3769
  return /* @__PURE__ */ jsx(CartContext.Provider, { value, children });
@@ -3466,6 +3776,6 @@ function useCartContext(options) {
3466
3776
  return context;
3467
3777
  }
3468
3778
 
3469
- export { BrowserPerformanceAdapter, BuyRuleType, CODE_AMOUNT_KEY, CUSTOMER_ATTRIBUTE_KEY, CUSTOMER_SCRIPT_GIFT_KEY, CartProvider, DeliveryPlusType, MAIN_PRODUCT_CODE, MEMBER_PRICE_ATTRIBUTE_KEY, OrderBasePriceType, OrderDiscountType, PLUS_MEMBER_TYPE, PlusMemberContext, PlusMemberMode, PlusMemberProvider, PriceBasePriceType, PriceDiscountType, RuleType, SCRIPT_CODE_AMOUNT_KEY, ShippingMethodMode, ShopifyContext, ShopifyProvider, SpendMoneyType, browserCartCookieAdapter, browserCookieAdapter, clearGeoLocationCache, createMockCartFromLines, currencyCodeMapping, defaultSWRMutationConfiguration, formatFunctionAutoFreeGift, formatScriptAutoFreeGift, gaTrack, getCachedGeoLocation, getCartAttributes, getDiscountEnvAttributeValue, getMatchedMainProductSubTotal, getQuery, getReferralAttributes, getUserType, hasPlusMemberInCart, hasPlusMemberInLines, normalizeAddToCartLines, preCheck, safeParse, trackAddToCartFBQ, trackAddToCartGA, trackBeginCheckoutGA, trackBuyNowFBQ, trackBuyNowGA, useAddCartLines, useAddToCart, useAllBlogs, useAllCollections, useAllProducts, useApplyCartCodes, useArticle, useArticles, useArticlesInBlog, useAutoRemovePlusMemberInCart, useAvailableDeliveryCoupon, useBlog, useBuyNow, useCalcAutoFreeGift, useCalcGiftsFromLines, useCalcOrderDiscount, useCartAttributes, useCartContext, useCartItemQuantityLimit, useCollection, useCollections, useCreateCart, useExposure, useGeoLocation, useHasPlusMemberInCart, useHasPlusMemberInLines, useIntersection, usePlusMemberCheckoutCustomAttributes, usePlusMemberContext, usePlusMemberNeedAddToCart, usePlusMemberVariants, usePrice, useProduct, useProductUrl, useProductsByHandles, useRemoveCartCodes, useRemoveCartLines, useReplaceCartPlusMember, useScriptAutoFreeGift, useSearch, useSelectedOptions, useShippingMethods, useShopify, useSite, useUpdateBuyerIdentity, useUpdateCartAttributes, useUpdateCartLines, useUpdateLineCodeAmountAttributes, useUpdateVariantQuery, useVariant, useVariantMedia };
3779
+ export { BrowserPerformanceAdapter, BuyRuleType, CODE_AMOUNT_KEY, CUSTOMER_ATTRIBUTE_KEY, CUSTOMER_SCRIPT_GIFT_KEY, CartProvider, DeliveryPlusType, MAIN_PRODUCT_CODE, MEMBER_PRICE_ATTRIBUTE_KEY, OrderBasePriceType, OrderDiscountType, PLUS_MEMBER_TYPE, PlusMemberContext, PlusMemberMode, PlusMemberProvider, PriceBasePriceType, PriceDiscountType, RuleType, SCRIPT_CODE_AMOUNT_KEY, ShippingMethodMode, ShopifyContext, ShopifyProvider, SpendMoneyType, browserCartCookieAdapter, browserCookieAdapter, clearGeoLocationCache, createMockCartFromLines, currencyCodeMapping, defaultSWRMutationConfiguration, formatFunctionAutoFreeGift, formatScriptAutoFreeGift, gaTrack, getCachedGeoLocation, getCartBasicAttributes, getDiscountEnvAttributeValue, getGA4Attributes, getGA4AttributesAsync, getGA4ClientId, getGA4Data, getGA4SessionId, getMatchedMainProductSubTotal, getOperatingSystem, getQuery, getReferralAttributes, getUserType, hasPlusMemberInCart, hasPlusMemberInLines, isAnyGift, isBuyGetGift, isFunctionGift, isScriptGift, normalizeAddToCartLines, preCheck, safeParse, trackAddToCartFBQ, trackAddToCartGA, trackBeginCheckoutGA, trackBuyNowFBQ, trackBuyNowGA, useAddCartLines, useAddToCart, useAllBlogs, useAllCollections, useAllProducts, useApplyCartCodes, useArticle, useArticles, useArticlesInBlog, useAutoRemoveFreeGifts, useAutoRemovePlusMemberInCart, useAvailableDeliveryCoupon, useBlog, useBuyNow, useCalcAutoFreeGift, useCalcGiftsFromLines, useCalcOrderDiscount, useCartAttributes, useCartContext, useCartItemQuantityLimit, useCollection, useCollections, useCreateCart, useExposure, useGeoLocation, useHasPlusMemberInCart, useHasPlusMemberInLines, useIntersection, usePlusMemberCheckoutCustomAttributes, usePlusMemberContext, usePlusMemberNeedAddToCart, usePlusMemberVariants, usePrice, useProduct, useProductUrl, useProductsByHandles, useRemoveCartCodes, useRemoveCartLines, useReplaceCartPlusMember, useScriptAutoFreeGift, useSearch, useSelectedOptions, useShippingMethods, useShopify, useSite, useUpdateBuyerIdentity, useUpdateCartAttributes, useUpdateCartLines, useUpdateLineCodeAmountAttributes, useUpdateVariantQuery, useVariant, useVariantMedia, waitForGtagReady };
3470
3780
  //# sourceMappingURL=index.mjs.map
3471
3781
  //# sourceMappingURL=index.mjs.map