@anker-in/shopify-react 1.1.2 → 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.
@@ -705,6 +705,52 @@ var checkAttributesUpdateNeeded = (oldAttributes, newAttributes, customAttribute
705
705
  (removeAttr) => oldAttributes.some((oldAttr) => oldAttr.key === removeAttr.key)
706
706
  );
707
707
  };
708
+ function waitForGtagReady(timeout = 1e4) {
709
+ return new Promise((resolve, reject) => {
710
+ const start = Date.now();
711
+ function check() {
712
+ if (typeof window !== "undefined" && typeof window.gtag !== "undefined") {
713
+ resolve();
714
+ } else if (Date.now() - start > timeout) {
715
+ reject(new Error("GA4 gtag not loaded"));
716
+ } else {
717
+ setTimeout(check, 50);
718
+ }
719
+ }
720
+ check();
721
+ });
722
+ }
723
+ var getGA4Data = async (measurementId = "G-R0BRMRK4CY") => {
724
+ try {
725
+ await waitForGtagReady();
726
+ const timeoutPromise = new Promise((resolve) => {
727
+ setTimeout(() => {
728
+ resolve({ clientId: "", sessionId: "" });
729
+ }, 300);
730
+ });
731
+ const dataPromise = new Promise((resolve) => {
732
+ if (!window.gtag) {
733
+ resolve({ clientId: "", sessionId: "" });
734
+ return;
735
+ }
736
+ window.gtag("get", measurementId, "client_id", (clientId) => {
737
+ window.gtag("get", measurementId, "session_id", (sessionId) => {
738
+ resolve({
739
+ clientId: clientId || "",
740
+ sessionId: sessionId || ""
741
+ });
742
+ });
743
+ });
744
+ });
745
+ return Promise.race([dataPromise, timeoutPromise]);
746
+ } catch (error) {
747
+ console.error("Failed to get GA4 data:", error);
748
+ return {
749
+ clientId: "",
750
+ sessionId: ""
751
+ };
752
+ }
753
+ };
708
754
  var getReferralAttributes = () => {
709
755
  const inviteCode = getLocalStorage("inviteCode") || Cookies5.get("inviteCode");
710
756
  const playModeId = getLocalStorage("playModeId") || Cookies5.get("playModeId");
@@ -721,6 +767,19 @@ var getReferralAttributes = () => {
721
767
  }
722
768
  return [];
723
769
  };
770
+ var getOperatingSystem = () => {
771
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
772
+ return "Unknown";
773
+ }
774
+ const userAgent = navigator.userAgent || navigator.vendor || window.opera;
775
+ if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
776
+ return "IOS";
777
+ }
778
+ if (/android/i.test(userAgent)) {
779
+ return "Android";
780
+ }
781
+ return "Unknown";
782
+ };
724
783
  var getUserType = (customer) => {
725
784
  let userInfo = Cookies5.get("userInfo");
726
785
  if (userInfo) {
@@ -742,12 +801,33 @@ var getUserType = (customer) => {
742
801
  }
743
802
  return "new_user_login";
744
803
  };
745
- function getCartAttributes({
804
+ function getGA4Attributes(ga4Data) {
805
+ if (!ga4Data?.clientId && !ga4Data?.sessionId) {
806
+ return [];
807
+ }
808
+ const attributes = [];
809
+ if (ga4Data.clientId) {
810
+ attributes.push({
811
+ key: "_ga4_client_id",
812
+ value: ga4Data.clientId
813
+ });
814
+ }
815
+ if (ga4Data.sessionId) {
816
+ attributes.push({
817
+ key: "_ga4_session_id",
818
+ value: ga4Data.sessionId
819
+ });
820
+ }
821
+ return attributes;
822
+ }
823
+ function getCartBasicAttributes({
746
824
  profile,
747
825
  customer,
748
826
  cart,
749
827
  memberType,
750
- currentUrl = ""
828
+ currentUrl = "",
829
+ appContext,
830
+ buyPath
751
831
  }) {
752
832
  const userType = getUserType(customer);
753
833
  const memberAttributes = [
@@ -774,12 +854,10 @@ function getCartAttributes({
774
854
  value: "1"
775
855
  });
776
856
  }
777
- const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
778
857
  const functionAttributes = [
779
858
  {
780
859
  key: CUSTOMER_ATTRIBUTE_KEY,
781
860
  value: JSON.stringify({
782
- discount_code: discountCodes,
783
861
  user_tags: customer?.tags || []
784
862
  })
785
863
  }
@@ -787,26 +865,38 @@ function getCartAttributes({
787
865
  const presellAttributes = [
788
866
  {
789
867
  key: "_presale",
790
- value: cart?.lineItems.some((item) => item?.variant?.metafields?.presell === "presell")
868
+ value: cart?.lineItems?.some((item) => item?.variant?.metafields?.presell === "presell")
791
869
  }
792
870
  ];
793
871
  const weightAttributes = [
794
872
  {
795
873
  key: "_weight",
796
- value: cart?.lineItems.reduce((acc, item) => {
874
+ value: cart?.lineItems?.reduce((acc, item) => {
797
875
  const itemWeight = new Decimal2(item.variant.weight ?? 0).times(item.quantity);
798
876
  return new Decimal2(acc).plus(itemWeight).toNumber();
799
877
  }, 0).toString()
800
- },
801
- {
802
- key: "_app_source_name",
803
- value: "dtc"
804
878
  }
805
879
  ];
806
880
  const trackingAttributes = [
807
881
  {
808
882
  key: "utm_params",
809
883
  value: currentUrl
884
+ },
885
+ {
886
+ key: "_app_source_name",
887
+ value: appContext?.isInApp && appContext?.appName ? appContext.appName : "dtc"
888
+ },
889
+ {
890
+ key: "_operating_system",
891
+ value: getOperatingSystem()
892
+ },
893
+ {
894
+ key: "_cart_id",
895
+ value: cart?.id
896
+ },
897
+ {
898
+ key: "_buy_path",
899
+ value: buyPath
810
900
  }
811
901
  ];
812
902
  const commonAttributes = [
@@ -826,21 +916,41 @@ var useCartAttributes = ({
826
916
  profile,
827
917
  customer,
828
918
  cart,
829
- memberType
919
+ memberType,
920
+ appContext,
921
+ buyPath
830
922
  }) => {
831
923
  const [currentUrl, setCurrentUrl] = useState("");
924
+ const [ga4Data, setGa4Data] = useState(null);
832
925
  useEffect(() => {
833
926
  setCurrentUrl(window.location.href);
834
927
  }, []);
928
+ useEffect(() => {
929
+ let isMounted = true;
930
+ getGA4Data().then((data) => {
931
+ if (isMounted) {
932
+ setGa4Data(data);
933
+ }
934
+ }).catch((error) => {
935
+ console.error("Failed to get GA4 data in useCartAttributes:", error);
936
+ });
937
+ return () => {
938
+ isMounted = false;
939
+ };
940
+ }, []);
835
941
  const attributes = useMemo(() => {
836
- return getCartAttributes({
942
+ const basicAttributes = getCartBasicAttributes({
837
943
  profile,
838
944
  customer,
839
945
  cart,
840
946
  memberType,
841
- currentUrl
947
+ currentUrl,
948
+ appContext,
949
+ buyPath
842
950
  });
843
- }, [profile, customer, cart, memberType, currentUrl]);
951
+ const ga4Attributes = getGA4Attributes(ga4Data);
952
+ return [...basicAttributes, ...ga4Attributes];
953
+ }, [profile, customer, cart, memberType, currentUrl, appContext, buyPath, ga4Data]);
844
954
  return useMemo(
845
955
  () => ({
846
956
  attributes
@@ -869,12 +979,9 @@ var useUpdateLineCodeAmountAttributes = ({
869
979
  const codeDiscount = line.discountAllocations?.find(
870
980
  (allocation) => mainProductDiscountCodes?.includes(allocation.code)
871
981
  );
872
- const hasFunctionEnvAttribute = line.customAttributes?.find(
873
- (attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY
874
- );
875
982
  const functionEnvValue = getDiscountEnvAttributeValue(line.customAttributes);
876
983
  const hasSameFunctionEnvAttribute = Number(functionEnvValue.discounted_amount) === Number(line.totalAmount);
877
- if (!hasSameFunctionEnvAttribute && hasFunctionEnvAttribute && !functionEnvValue.is_gift) {
984
+ if (!hasSameFunctionEnvAttribute && !functionEnvValue.is_gift) {
878
985
  attrNeedUpdate.push({
879
986
  key: CUSTOMER_ATTRIBUTE_KEY,
880
987
  value: JSON.stringify({
@@ -1062,13 +1169,14 @@ var CartContext = createContext(null);
1062
1169
  function CartProvider({
1063
1170
  children,
1064
1171
  // swrOptions,
1065
- autoFreeGiftConfig,
1066
- gradientGiftsConfig,
1172
+ functionAutoFreeGiftConfig,
1173
+ scriptAutoFreeGiftConfig,
1067
1174
  profile,
1068
1175
  customer,
1069
1176
  locale,
1070
1177
  metafieldIdentifiers,
1071
- memberSetting
1178
+ memberSetting,
1179
+ appContext
1072
1180
  }) {
1073
1181
  const { client, cartCookieAdapter } = useShopify();
1074
1182
  const [customAttributes, setCustomAttributes] = useState([]);
@@ -1113,7 +1221,8 @@ function CartProvider({
1113
1221
  profile,
1114
1222
  customer,
1115
1223
  cart,
1116
- memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0)
1224
+ memberType: hasPlusMember ? "2" : String(profile?.memberType ?? 0),
1225
+ appContext
1117
1226
  });
1118
1227
  useRequest(
1119
1228
  () => {
@@ -1167,9 +1276,13 @@ function CartProvider({
1167
1276
  },
1168
1277
  [setCustomAttributes]
1169
1278
  );
1170
- const functionAutoFreeGiftResult = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer);
1279
+ const functionAutoFreeGiftResult = useCalcAutoFreeGift(
1280
+ cart,
1281
+ functionAutoFreeGiftConfig || [],
1282
+ customer
1283
+ );
1171
1284
  const scriptAutoFreeGiftResult = useScriptAutoFreeGift({
1172
- campaign: gradientGiftsConfig || null,
1285
+ campaign: scriptAutoFreeGiftConfig,
1173
1286
  _giveaway: CUSTOMER_SCRIPT_GIFT_KEY,
1174
1287
  cart,
1175
1288
  profile
@@ -1177,10 +1290,10 @@ function CartProvider({
1177
1290
  const formattedScriptGifts = useMemo(() => {
1178
1291
  return formatScriptAutoFreeGift({
1179
1292
  scriptAutoFreeGiftResult,
1180
- gradient_gifts: gradientGiftsConfig,
1293
+ gradient_gifts: scriptAutoFreeGiftConfig,
1181
1294
  locale
1182
1295
  });
1183
- }, [scriptAutoFreeGiftResult, gradientGiftsConfig, locale]);
1296
+ }, [scriptAutoFreeGiftResult, scriptAutoFreeGiftConfig, locale]);
1184
1297
  const formattedFunctionGifts = useMemo(() => {
1185
1298
  return formatFunctionAutoFreeGift({
1186
1299
  qualifyingGift: functionAutoFreeGiftResult?.qualifyingGift || null,
@@ -1228,6 +1341,12 @@ function CartProvider({
1228
1341
  const giftLinesCount = giftNeedAddToCartLines?.reduce((acc, item) => acc + (item.quantity || 1), 0) || 0;
1229
1342
  return cartLinesCount + giftLinesCount;
1230
1343
  }, [cart?.lineItems, giftNeedAddToCartLines]);
1344
+ const autoRemoveFreeGiftsOptions = useMemo(() => {
1345
+ return {
1346
+ removeFunctionGifts: !!functionAutoFreeGiftConfig,
1347
+ removeScriptGifts: !!scriptAutoFreeGiftConfig
1348
+ };
1349
+ }, [functionAutoFreeGiftConfig, scriptAutoFreeGiftConfig]);
1231
1350
  const value = useMemo(
1232
1351
  () => ({
1233
1352
  totalQuantity,
@@ -1242,8 +1361,8 @@ function CartProvider({
1242
1361
  customer,
1243
1362
  isCodeChanging,
1244
1363
  setIsCodeChanging,
1245
- autoFreeGiftConfig,
1246
- gradientGiftsConfig,
1364
+ functionAutoFreeGiftConfig,
1365
+ scriptAutoFreeGiftConfig,
1247
1366
  setLoadingState,
1248
1367
  loadingState,
1249
1368
  // function满赠
@@ -1256,7 +1375,9 @@ function CartProvider({
1256
1375
  setScriptAutoFreeGift,
1257
1376
  giftNeedAddToCartLines,
1258
1377
  metafieldIdentifiers,
1259
- memberSetting
1378
+ memberSetting,
1379
+ appContext,
1380
+ autoRemoveFreeGiftsOptions
1260
1381
  }),
1261
1382
  [
1262
1383
  cart,
@@ -1268,8 +1389,8 @@ function CartProvider({
1268
1389
  removeCustomAttributes,
1269
1390
  locale,
1270
1391
  isCodeChanging,
1271
- autoFreeGiftConfig,
1272
- gradientGiftsConfig,
1392
+ functionAutoFreeGiftConfig,
1393
+ scriptAutoFreeGiftConfig,
1273
1394
  loadingState,
1274
1395
  // function满赠
1275
1396
  functionAutoFreeGift,
@@ -1283,7 +1404,9 @@ function CartProvider({
1283
1404
  metafieldIdentifiers,
1284
1405
  customer,
1285
1406
  profile,
1286
- memberSetting
1407
+ memberSetting,
1408
+ appContext,
1409
+ autoRemoveFreeGiftsOptions
1287
1410
  ]
1288
1411
  );
1289
1412
  return /* @__PURE__ */ jsx(CartContext.Provider, { value, children });