@shopify/hydrogen-react 2026.4.3 → 2026.4.5
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/browser-dev/ShopifyProvider.mjs.map +1 -1
- package/dist/browser-dev/analytics-schema-custom-storefront-customer-tracking.mjs +1 -1
- package/dist/browser-dev/load-script.mjs +5 -5
- package/dist/browser-dev/load-script.mjs.map +1 -1
- package/dist/browser-dev/packages/hydrogen-react/package.mjs +1 -1
- package/dist/browser-dev/packages/hydrogen-react/package.mjs.map +1 -1
- package/dist/browser-dev/tracking-utils.mjs +17 -58
- package/dist/browser-dev/tracking-utils.mjs.map +1 -1
- package/dist/browser-dev/useShopifyCookies.mjs +34 -97
- package/dist/browser-dev/useShopifyCookies.mjs.map +1 -1
- package/dist/browser-prod/ShopifyProvider.mjs.map +1 -1
- package/dist/browser-prod/analytics-schema-custom-storefront-customer-tracking.mjs +1 -1
- package/dist/browser-prod/load-script.mjs +5 -5
- package/dist/browser-prod/load-script.mjs.map +1 -1
- package/dist/browser-prod/packages/hydrogen-react/package.mjs +1 -1
- package/dist/browser-prod/packages/hydrogen-react/package.mjs.map +1 -1
- package/dist/browser-prod/tracking-utils.mjs +17 -58
- package/dist/browser-prod/tracking-utils.mjs.map +1 -1
- package/dist/browser-prod/useShopifyCookies.mjs +34 -97
- package/dist/browser-prod/useShopifyCookies.mjs.map +1 -1
- package/dist/node-dev/ShopifyProvider.js.map +1 -1
- package/dist/node-dev/ShopifyProvider.mjs.map +1 -1
- package/dist/node-dev/analytics-schema-custom-storefront-customer-tracking.js +1 -1
- package/dist/node-dev/analytics-schema-custom-storefront-customer-tracking.mjs +1 -1
- package/dist/node-dev/load-script.js +6 -4
- package/dist/node-dev/load-script.js.map +1 -1
- package/dist/node-dev/load-script.mjs +5 -5
- package/dist/node-dev/load-script.mjs.map +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.js +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.js.map +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.mjs +1 -1
- package/dist/node-dev/packages/hydrogen-react/package.mjs.map +1 -1
- package/dist/node-dev/tracking-utils.js +17 -58
- package/dist/node-dev/tracking-utils.js.map +1 -1
- package/dist/node-dev/tracking-utils.mjs +17 -58
- package/dist/node-dev/tracking-utils.mjs.map +1 -1
- package/dist/node-dev/useShopifyCookies.js +34 -97
- package/dist/node-dev/useShopifyCookies.js.map +1 -1
- package/dist/node-dev/useShopifyCookies.mjs +34 -97
- package/dist/node-dev/useShopifyCookies.mjs.map +1 -1
- package/dist/node-prod/ShopifyProvider.js.map +1 -1
- package/dist/node-prod/ShopifyProvider.mjs.map +1 -1
- package/dist/node-prod/analytics-schema-custom-storefront-customer-tracking.js +1 -1
- package/dist/node-prod/analytics-schema-custom-storefront-customer-tracking.mjs +1 -1
- package/dist/node-prod/load-script.js +6 -4
- package/dist/node-prod/load-script.js.map +1 -1
- package/dist/node-prod/load-script.mjs +5 -5
- package/dist/node-prod/load-script.mjs.map +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.js +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.js.map +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.mjs +1 -1
- package/dist/node-prod/packages/hydrogen-react/package.mjs.map +1 -1
- package/dist/node-prod/tracking-utils.js +17 -58
- package/dist/node-prod/tracking-utils.js.map +1 -1
- package/dist/node-prod/tracking-utils.mjs +17 -58
- package/dist/node-prod/tracking-utils.mjs.map +1 -1
- package/dist/node-prod/useShopifyCookies.js +34 -97
- package/dist/node-prod/useShopifyCookies.js.map +1 -1
- package/dist/node-prod/useShopifyCookies.mjs +34 -97
- package/dist/node-prod/useShopifyCookies.mjs.map +1 -1
- package/dist/types/ShopifyProvider.d.ts +3 -0
- package/dist/types/tracking-utils.d.ts +5 -4
- package/dist/types/useShopifyCookies.d.ts +14 -33
- package/dist/umd/hydrogen-react.dev.js +59 -166
- package/dist/umd/hydrogen-react.dev.js.map +1 -1
- package/dist/umd/hydrogen-react.prod.js +4 -4
- package/dist/umd/hydrogen-react.prod.js.map +1 -1
- package/package.json +1 -1
|
@@ -8,6 +8,10 @@ function loadScript(src, options) {
|
|
|
8
8
|
const script = document.createElement("script");
|
|
9
9
|
if (options?.module) script.type = "module";
|
|
10
10
|
else script.type = "text/javascript";
|
|
11
|
+
const attributes = options?.attributes;
|
|
12
|
+
if (attributes) Object.keys(attributes).forEach((key) => {
|
|
13
|
+
script.setAttribute(key, attributes[key]);
|
|
14
|
+
});
|
|
11
15
|
script.src = src;
|
|
12
16
|
script.onload = () => {
|
|
13
17
|
resolve(true);
|
|
@@ -17,10 +21,6 @@ function loadScript(src, options) {
|
|
|
17
21
|
};
|
|
18
22
|
if (options?.in === "head") document.head.appendChild(script);
|
|
19
23
|
else document.body.appendChild(script);
|
|
20
|
-
const attributes = options?.attributes;
|
|
21
|
-
if (attributes) Object.keys(attributes).forEach((key) => {
|
|
22
|
-
script.setAttribute(key, attributes[key]);
|
|
23
|
-
});
|
|
24
24
|
});
|
|
25
25
|
SCRIPTS_LOADED[src] = promise;
|
|
26
26
|
return promise;
|
|
@@ -37,6 +37,6 @@ function useLoadScript(url, options) {
|
|
|
37
37
|
return status;
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
|
-
export { useLoadScript };
|
|
40
|
+
export { loadScript, useLoadScript };
|
|
41
41
|
|
|
42
42
|
//# sourceMappingURL=load-script.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-script.mjs","names":[],"sources":["../../src/load-script.tsx"],"sourcesContent":["import {useState, useEffect} from 'react';\n\nconst SCRIPTS_LOADED: Record<string, Promise<boolean>> = {};\n\ntype LoadScriptOptions = {\n module?: boolean;\n in?: 'head' | 'body';\n attributes?: Record<string, string>;\n};\n\nexport function loadScript(\n src: string,\n options?: LoadScriptOptions,\n): Promise<boolean> {\n const isScriptLoaded = SCRIPTS_LOADED[src];\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (isScriptLoaded) {\n return isScriptLoaded;\n }\n\n const promise = new Promise<boolean>((resolve, reject) => {\n const script = document.createElement('script');\n if (options?.module) {\n script.type = 'module';\n } else {\n script.type = 'text/javascript';\n }\n script.src = src;\n script.onload = (): void => {\n resolve(true);\n };\n script.onerror = (): void => {\n reject(false);\n };\n if (options?.in === 'head') {\n document.head.appendChild(script);\n } else {\n document.body.appendChild(script);\n }\n
|
|
1
|
+
{"version":3,"file":"load-script.mjs","names":[],"sources":["../../src/load-script.tsx"],"sourcesContent":["import {useState, useEffect} from 'react';\n\nconst SCRIPTS_LOADED: Record<string, Promise<boolean>> = {};\n\ntype LoadScriptOptions = {\n module?: boolean;\n in?: 'head' | 'body';\n attributes?: Record<string, string>;\n};\n\nexport function loadScript(\n src: string,\n options?: LoadScriptOptions,\n): Promise<boolean> {\n const isScriptLoaded = SCRIPTS_LOADED[src];\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (isScriptLoaded) {\n return isScriptLoaded;\n }\n\n const promise = new Promise<boolean>((resolve, reject) => {\n const script = document.createElement('script');\n if (options?.module) {\n script.type = 'module';\n } else {\n script.type = 'text/javascript';\n }\n const attributes = options?.attributes;\n if (attributes) {\n Object.keys(attributes).forEach((key) => {\n script.setAttribute(key, attributes[key]);\n });\n }\n\n script.src = src;\n script.onload = (): void => {\n resolve(true);\n };\n script.onerror = (): void => {\n reject(false);\n };\n if (options?.in === 'head') {\n document.head.appendChild(script);\n } else {\n document.body.appendChild(script);\n }\n });\n\n SCRIPTS_LOADED[src] = promise;\n\n return promise;\n}\n\n/** @publicDocs */\nexport type LoadScriptParams = Parameters<typeof loadScript>;\n\n/**\n * The `useLoadScript` hook loads an external script tag in the browser. It allows React components to lazy-load large third-party dependencies.\n * @publicDocs\n */\nexport function useLoadScript(\n url: LoadScriptParams[0],\n options?: LoadScriptParams[1],\n): ScriptState {\n const [status, setStatus] = useState<ScriptState>('loading');\n\n useEffect(\n () => {\n loadScript(url, options)\n .then(() => setStatus('done'))\n .catch(() => setStatus('error'));\n },\n // Ignore options changes since it won't trigger a new load.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [url],\n );\n\n return status;\n}\n\ntype ScriptState = 'loading' | 'done' | 'error';\n"],"mappings":";;AAEA,IAAM,iBAAmD,EAAE;AAQ3D,SAAgB,WACd,KACA,SACkB;CAClB,MAAM,iBAAiB,eAAe;AAGtC,KAAI,eACF,QAAO;CAGT,MAAM,UAAU,IAAI,SAAkB,SAAS,WAAW;EACxD,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,MAAI,SAAS,OACX,QAAO,OAAO;MAEd,QAAO,OAAO;EAEhB,MAAM,aAAa,SAAS;AAC5B,MAAI,WACF,QAAO,KAAK,WAAW,CAAC,SAAS,QAAQ;AACvC,UAAO,aAAa,KAAK,WAAW,KAAK;IACzC;AAGJ,SAAO,MAAM;AACb,SAAO,eAAqB;AAC1B,WAAQ,KAAK;;AAEf,SAAO,gBAAsB;AAC3B,UAAO,MAAM;;AAEf,MAAI,SAAS,OAAO,OAClB,UAAS,KAAK,YAAY,OAAO;MAEjC,UAAS,KAAK,YAAY,OAAO;GAEnC;AAEF,gBAAe,OAAO;AAEtB,QAAO;;;;;;AAUT,SAAgB,cACd,KACA,SACa;CACb,MAAM,CAAC,QAAQ,aAAa,SAAsB,UAAU;AAE5D,iBACQ;AACJ,aAAW,KAAK,QAAQ,CACrB,WAAW,UAAU,OAAO,CAAC,CAC7B,YAAY,UAAU,QAAQ,CAAC;IAIpC,CAAC,IAAI,CACN;AAED,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","names":[],"sources":["../../../../package.json"],"sourcesContent":["{\n \"name\": \"@shopify/hydrogen-react\",\n \"version\": \"2026.4.
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../../../../package.json"],"sourcesContent":["{\n \"name\": \"@shopify/hydrogen-react\",\n \"version\": \"2026.4.5\",\n \"description\": \"React components, hooks, and utilities for creating custom Shopify storefronts\",\n \"homepage\": \"https://github.com/Shopify/hydrogen/tree/main/packages/hydrogen-react\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\",\n \"@shopify:registry\": \"https://registry.npmjs.org\"\n },\n \"files\": [\n \"dist\",\n \"storefront.schema.json\",\n \"customer-account.schema.json\"\n ],\n \"type\": \"commonjs\",\n \"exports\": {\n \".\": {\n \"node\": {\n \"require\": {\n \"types\": \"./dist/types/index.d.cts\",\n \"development\": \"./dist/node-dev/index.js\",\n \"default\": \"./dist/node-prod/index.js\"\n },\n \"import\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"development\": \"./dist/node-dev/index.mjs\",\n \"default\": \"./dist/node-prod/index.mjs\"\n },\n \"default\": \"./dist/node-prod/index.js\"\n },\n \"module\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"development\": \"./dist/browser-dev/index.mjs\",\n \"default\": \"./dist/browser-prod/index.mjs\"\n },\n \"import\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"development\": \"./dist/browser-dev/index.mjs\",\n \"default\": \"./dist/browser-prod/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/types/index.d.cts\",\n \"development\": \"./dist/node-dev/index.js\",\n \"default\": \"./dist/node-prod/index.js\"\n },\n \"default\": \"./dist/browser-prod/index.mjs\"\n },\n \"./storefront-api-types\": \"./dist/types/storefront-api-types.d.ts\",\n \"./storefront.schema.json\": \"./storefront.schema.json\",\n \"./customer-account.schema.json\": \"./customer-account.schema.json\",\n \"./customer-account-api-types\": \"./dist/types/customer-account-api-types.d.ts\",\n \"./package.json\": \"./package.json\",\n \"./*\": {\n \"node\": {\n \"require\": {\n \"types\": \"./dist/types/*.d.cts\",\n \"development\": \"./dist/node-dev/*.js\",\n \"default\": \"./dist/node-prod/*.js\"\n },\n \"import\": {\n \"types\": \"./dist/types/*.d.ts\",\n \"development\": \"./dist/node-dev/*.mjs\",\n \"default\": \"./dist/node-prod/*.mjs\"\n },\n \"default\": \"./dist/node-prod/*.js\"\n },\n \"module\": {\n \"types\": \"./dist/types/*.d.ts\",\n \"development\": \"./dist/browser-dev/*.mjs\",\n \"default\": \"./dist/browser-prod/*.mjs\"\n },\n \"import\": {\n \"types\": \"./dist/types/*.d.ts\",\n \"development\": \"./dist/browser-dev/*.mjs\",\n \"default\": \"./dist/browser-prod/*.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/types/*.d.cts\",\n \"development\": \"./dist/node-dev/*.js\",\n \"default\": \"./dist/node-prod/*.js\"\n },\n \"default\": \"./dist/browser-prod/*.mjs\"\n }\n },\n \"typesVersions\": {\n \"*\": {\n \"storefront-api-types\": [\n \"./dist/types/storefront-api-types.d.ts\"\n ]\n }\n },\n \"main\": \"./dist/node-prod/index.js\",\n \"module\": \"./dist/node-prod/index.mjs\",\n \"browser\": \"./dist/browser-prod/index.mjs\",\n \"types\": \"./dist/types/index.d.ts\",\n \"unpkg\": \"./dist/umd/hydrogen-react.prod.js\",\n \"jsdelivr\": \"./dist/umd/hydrogen-react.prod.js\",\n \"sideEffects\": false,\n \"scripts\": {\n \"build-docs\": \"sh ./docs/build-docs.sh && pnpm run format\",\n \"clean-dist\": \"rimraf ./dist\",\n \"dev\": \"run-s dev:demo\",\n \"dev:story\": \"ladle serve\",\n \"dev:demo\": \"run-p dev:demo:* copy-api-types\",\n \"dev:demo:browser-dev\": \"vite build --watch --emptyOutDir false --clearScreen false --mode devbuild\",\n \"dev:demo:ts\": \"tsc --watch --emitDeclarationOnly\",\n \"build\": \"npm-run-all --sequential clean-dist --parallel build:vite:* build:tsc:es --parallel build:tsc:cjs copy-api-types\",\n \"build:vite:browser-dev\": \"vite build --mode devbuild\",\n \"build:vite:browser-prod\": \"vite build\",\n \"build:vite:node-dev\": \"vite build --mode devbuild --ssr\",\n \"build:vite:node-prod\": \"vite build --ssr\",\n \"build:vite:umddev\": \"vite build --mode umdbuilddev\",\n \"build:vite:umdprod\": \"vite build --mode umdbuild\",\n \"build:tsc:cjs\": \"cpy ./dist/types/index.d.ts ./dist/types/ --rename=index.d.cts --flat\",\n \"build:tsc:es\": \"tsc --emitDeclarationOnly --project tsconfig.typeoutput.json\",\n \"copy-api-types\": \"cpy ./src/storefront-api-types.d.ts ./src/customer-account-api-types.d.ts ./dist/types/ --flat\",\n \"format\": \"prettier --write \\\"{src,docs}/**/*\\\" --ignore-unknown\",\n \"graphql-types\": \"graphql-codegen --config codegen.ts && pnpm run format\",\n \"test\": \"vitest run --coverage\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"run-p typecheck:*\",\n \"typecheck:code\": \"tsc --noEmit\",\n \"typecheck:examples\": \"tsc --noEmit --project tsconfig.examples.json\",\n \"preview-docs\": \"pnpm --dir ../../docs/preview run dev\"\n },\n \"devDependencies\": {\n \"@faker-js/faker\": \"^9.4.0\",\n \"@graphql-codegen/add\": \"^5.0.3\",\n \"@graphql-codegen/cli\": \"^5.0.4\",\n \"@graphql-codegen/introspection\": \"^4.0.3\",\n \"@graphql-codegen/typescript\": \"^4.1.3\",\n \"@ladle/react\": \"^5.0.1\",\n \"@shopify/generate-docs\": \"catalog:\",\n \"@testing-library/jest-dom\": \"^6.6.3\",\n \"@testing-library/react\": \"^14.0.0\",\n \"@testing-library/user-event\": \"^14.6.1\",\n \"@types/react\": \"catalog:\",\n \"@types/react-dom\": \"catalog:\",\n \"@vitejs/plugin-react\": \"^6.0.1\",\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"cpy-cli\": \"^5.0.0\",\n \"eslint\": \"9.19.0\",\n \"eslint-config-prettier\": \"10.0.1\",\n \"eslint-import-resolver-typescript\": \"3.7.0\",\n \"eslint-plugin-eslint-comments\": \"3.2.0\",\n \"eslint-plugin-import\": \"2.31.0\",\n \"eslint-plugin-jest\": \"28.11.0\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-node\": \"11.1.0\",\n \"eslint-plugin-prettier\": \"4.2.1\",\n \"eslint-plugin-react\": \"7.37.4\",\n \"eslint-plugin-react-hooks\": \"5.1.0\",\n \"eslint-plugin-simple-import-sort\": \"12.1.1\",\n \"eslint-plugin-tsdoc\": \"0.2.14\",\n \"happy-dom\": \"^20.8.9\",\n \"npm-run-all\": \"^4.1.5\",\n \"react\": \"catalog:\",\n \"react-dom\": \"catalog:\",\n \"rimraf\": \"^6.0.1\",\n \"ts-expect\": \"^1.3.0\",\n \"typescript\": \"5.9.2\",\n \"vite\": \"^8.0.1\",\n \"vitest\": \"^3.2.4\"\n },\n \"peerDependencies\": {\n \"react\": \"^18.3.1 || ~19.0.3 || ~19.1.4 || ^19.2.3\",\n \"react-dom\": \"^18.3.1 || ~19.0.3 || ~19.1.4 || ^19.2.3\",\n \"vite\": \"^5.1.0 || ^6.2.1 || ^7.0.0 || ^8.0.0\"\n },\n \"dependencies\": {\n \"@google/model-viewer\": \"^4.0.0\",\n \"@xstate/fsm\": \"2.0.0\",\n \"ast-v8-to-istanbul\": \"^0.3.11\",\n \"graphql\": \"^16.10.0\",\n \"type-fest\": \"^4.33.0\",\n \"worktop\": \"^0.7.3\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Shopify/hydrogen.git\",\n \"directory\": \"packages/hydrogen-react\"\n },\n \"bugs\": \"https://github.com/shopify/hydrogen/issues\"\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.mjs","names":[],"sources":["../../../../package.json"],"sourcesContent":["{\n \"name\": \"@shopify/hydrogen-react\",\n \"version\": \"2026.4.
|
|
1
|
+
{"version":3,"file":"package.mjs","names":[],"sources":["../../../../package.json"],"sourcesContent":["{\n \"name\": \"@shopify/hydrogen-react\",\n \"version\": \"2026.4.5\",\n \"description\": \"React components, hooks, and utilities for creating custom Shopify storefronts\",\n \"homepage\": \"https://github.com/Shopify/hydrogen/tree/main/packages/hydrogen-react\",\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\",\n \"@shopify:registry\": \"https://registry.npmjs.org\"\n },\n \"files\": [\n \"dist\",\n \"storefront.schema.json\",\n \"customer-account.schema.json\"\n ],\n \"type\": \"commonjs\",\n \"exports\": {\n \".\": {\n \"node\": {\n \"require\": {\n \"types\": \"./dist/types/index.d.cts\",\n \"development\": \"./dist/node-dev/index.js\",\n \"default\": \"./dist/node-prod/index.js\"\n },\n \"import\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"development\": \"./dist/node-dev/index.mjs\",\n \"default\": \"./dist/node-prod/index.mjs\"\n },\n \"default\": \"./dist/node-prod/index.js\"\n },\n \"module\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"development\": \"./dist/browser-dev/index.mjs\",\n \"default\": \"./dist/browser-prod/index.mjs\"\n },\n \"import\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"development\": \"./dist/browser-dev/index.mjs\",\n \"default\": \"./dist/browser-prod/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/types/index.d.cts\",\n \"development\": \"./dist/node-dev/index.js\",\n \"default\": \"./dist/node-prod/index.js\"\n },\n \"default\": \"./dist/browser-prod/index.mjs\"\n },\n \"./storefront-api-types\": \"./dist/types/storefront-api-types.d.ts\",\n \"./storefront.schema.json\": \"./storefront.schema.json\",\n \"./customer-account.schema.json\": \"./customer-account.schema.json\",\n \"./customer-account-api-types\": \"./dist/types/customer-account-api-types.d.ts\",\n \"./package.json\": \"./package.json\",\n \"./*\": {\n \"node\": {\n \"require\": {\n \"types\": \"./dist/types/*.d.cts\",\n \"development\": \"./dist/node-dev/*.js\",\n \"default\": \"./dist/node-prod/*.js\"\n },\n \"import\": {\n \"types\": \"./dist/types/*.d.ts\",\n \"development\": \"./dist/node-dev/*.mjs\",\n \"default\": \"./dist/node-prod/*.mjs\"\n },\n \"default\": \"./dist/node-prod/*.js\"\n },\n \"module\": {\n \"types\": \"./dist/types/*.d.ts\",\n \"development\": \"./dist/browser-dev/*.mjs\",\n \"default\": \"./dist/browser-prod/*.mjs\"\n },\n \"import\": {\n \"types\": \"./dist/types/*.d.ts\",\n \"development\": \"./dist/browser-dev/*.mjs\",\n \"default\": \"./dist/browser-prod/*.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/types/*.d.cts\",\n \"development\": \"./dist/node-dev/*.js\",\n \"default\": \"./dist/node-prod/*.js\"\n },\n \"default\": \"./dist/browser-prod/*.mjs\"\n }\n },\n \"typesVersions\": {\n \"*\": {\n \"storefront-api-types\": [\n \"./dist/types/storefront-api-types.d.ts\"\n ]\n }\n },\n \"main\": \"./dist/node-prod/index.js\",\n \"module\": \"./dist/node-prod/index.mjs\",\n \"browser\": \"./dist/browser-prod/index.mjs\",\n \"types\": \"./dist/types/index.d.ts\",\n \"unpkg\": \"./dist/umd/hydrogen-react.prod.js\",\n \"jsdelivr\": \"./dist/umd/hydrogen-react.prod.js\",\n \"sideEffects\": false,\n \"scripts\": {\n \"build-docs\": \"sh ./docs/build-docs.sh && pnpm run format\",\n \"clean-dist\": \"rimraf ./dist\",\n \"dev\": \"run-s dev:demo\",\n \"dev:story\": \"ladle serve\",\n \"dev:demo\": \"run-p dev:demo:* copy-api-types\",\n \"dev:demo:browser-dev\": \"vite build --watch --emptyOutDir false --clearScreen false --mode devbuild\",\n \"dev:demo:ts\": \"tsc --watch --emitDeclarationOnly\",\n \"build\": \"npm-run-all --sequential clean-dist --parallel build:vite:* build:tsc:es --parallel build:tsc:cjs copy-api-types\",\n \"build:vite:browser-dev\": \"vite build --mode devbuild\",\n \"build:vite:browser-prod\": \"vite build\",\n \"build:vite:node-dev\": \"vite build --mode devbuild --ssr\",\n \"build:vite:node-prod\": \"vite build --ssr\",\n \"build:vite:umddev\": \"vite build --mode umdbuilddev\",\n \"build:vite:umdprod\": \"vite build --mode umdbuild\",\n \"build:tsc:cjs\": \"cpy ./dist/types/index.d.ts ./dist/types/ --rename=index.d.cts --flat\",\n \"build:tsc:es\": \"tsc --emitDeclarationOnly --project tsconfig.typeoutput.json\",\n \"copy-api-types\": \"cpy ./src/storefront-api-types.d.ts ./src/customer-account-api-types.d.ts ./dist/types/ --flat\",\n \"format\": \"prettier --write \\\"{src,docs}/**/*\\\" --ignore-unknown\",\n \"graphql-types\": \"graphql-codegen --config codegen.ts && pnpm run format\",\n \"test\": \"vitest run --coverage\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"run-p typecheck:*\",\n \"typecheck:code\": \"tsc --noEmit\",\n \"typecheck:examples\": \"tsc --noEmit --project tsconfig.examples.json\",\n \"preview-docs\": \"pnpm --dir ../../docs/preview run dev\"\n },\n \"devDependencies\": {\n \"@faker-js/faker\": \"^9.4.0\",\n \"@graphql-codegen/add\": \"^5.0.3\",\n \"@graphql-codegen/cli\": \"^5.0.4\",\n \"@graphql-codegen/introspection\": \"^4.0.3\",\n \"@graphql-codegen/typescript\": \"^4.1.3\",\n \"@ladle/react\": \"^5.0.1\",\n \"@shopify/generate-docs\": \"catalog:\",\n \"@testing-library/jest-dom\": \"^6.6.3\",\n \"@testing-library/react\": \"^14.0.0\",\n \"@testing-library/user-event\": \"^14.6.1\",\n \"@types/react\": \"catalog:\",\n \"@types/react-dom\": \"catalog:\",\n \"@vitejs/plugin-react\": \"^6.0.1\",\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"cpy-cli\": \"^5.0.0\",\n \"eslint\": \"9.19.0\",\n \"eslint-config-prettier\": \"10.0.1\",\n \"eslint-import-resolver-typescript\": \"3.7.0\",\n \"eslint-plugin-eslint-comments\": \"3.2.0\",\n \"eslint-plugin-import\": \"2.31.0\",\n \"eslint-plugin-jest\": \"28.11.0\",\n \"eslint-plugin-jsx-a11y\": \"6.10.2\",\n \"eslint-plugin-node\": \"11.1.0\",\n \"eslint-plugin-prettier\": \"4.2.1\",\n \"eslint-plugin-react\": \"7.37.4\",\n \"eslint-plugin-react-hooks\": \"5.1.0\",\n \"eslint-plugin-simple-import-sort\": \"12.1.1\",\n \"eslint-plugin-tsdoc\": \"0.2.14\",\n \"happy-dom\": \"^20.8.9\",\n \"npm-run-all\": \"^4.1.5\",\n \"react\": \"catalog:\",\n \"react-dom\": \"catalog:\",\n \"rimraf\": \"^6.0.1\",\n \"ts-expect\": \"^1.3.0\",\n \"typescript\": \"5.9.2\",\n \"vite\": \"^8.0.1\",\n \"vitest\": \"^3.2.4\"\n },\n \"peerDependencies\": {\n \"react\": \"^18.3.1 || ~19.0.3 || ~19.1.4 || ^19.2.3\",\n \"react-dom\": \"^18.3.1 || ~19.0.3 || ~19.1.4 || ^19.2.3\",\n \"vite\": \"^5.1.0 || ^6.2.1 || ^7.0.0 || ^8.0.0\"\n },\n \"dependencies\": {\n \"@google/model-viewer\": \"^4.0.0\",\n \"@xstate/fsm\": \"2.0.0\",\n \"ast-v8-to-istanbul\": \"^0.3.11\",\n \"graphql\": \"^16.10.0\",\n \"type-fest\": \"^4.33.0\",\n \"worktop\": \"^0.7.3\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Shopify/hydrogen.git\",\n \"directory\": \"packages/hydrogen-react\"\n },\n \"bugs\": \"https://github.com/shopify/hydrogen/issues\"\n}\n"],"mappings":""}
|
|
@@ -3,68 +3,27 @@
|
|
|
3
3
|
var SHOPIFY_VISIT_TOKEN_HEADER = "X-Shopify-VisitToken";
|
|
4
4
|
/** Storefront API header for UniqueToken */
|
|
5
5
|
var SHOPIFY_UNIQUE_TOKEN_HEADER = "X-Shopify-UniqueToken";
|
|
6
|
-
var cachedTrackingValues = { current: null };
|
|
7
6
|
/**
|
|
8
|
-
* Retrieves user session tracking values for analytics and marketing from the
|
|
7
|
+
* Retrieves user session tracking values for analytics and marketing from the
|
|
8
|
+
* browser environment. Customer Privacy API token readers are authoritative
|
|
9
|
+
* when available, including when consent denies tracking. Deprecated
|
|
10
|
+
* `_shopify_y`/`_shopify_s` cookies are read only without an API token reader.
|
|
11
|
+
* Consent comes from CTA's cache or the legacy `_tracking_consent` cookie.
|
|
9
12
|
* @publicDocs
|
|
10
13
|
*/
|
|
11
14
|
function getTrackingValues() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (matchedHost === currentHost || sfapiPath && matchedHost?.endsWith(`.${currentHost}`)) {
|
|
25
|
-
const values = extractFromPerformanceEntry(entry);
|
|
26
|
-
if (values) {
|
|
27
|
-
matchedValues = values;
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (matchedValues) trackingValues = matchedValues;
|
|
33
|
-
if (trackingValues) cachedTrackingValues.current = trackingValues;
|
|
34
|
-
else if (cachedTrackingValues.current) trackingValues = cachedTrackingValues.current;
|
|
35
|
-
if (!trackingValues) {
|
|
36
|
-
const navigationEntries = performance.getEntriesByType("navigation")[0];
|
|
37
|
-
trackingValues = extractFromPerformanceEntry(navigationEntries, false);
|
|
38
|
-
}
|
|
39
|
-
} catch {}
|
|
40
|
-
if (!trackingValues) {
|
|
41
|
-
const cookie = typeof arguments[0] === "string" ? arguments[0] : typeof document !== "undefined" ? document.cookie : "";
|
|
42
|
-
trackingValues = {
|
|
43
|
-
uniqueToken: cookie.match(/\b_shopify_y=([^;]+)/)?.[1] || "",
|
|
44
|
-
visitToken: cookie.match(/\b_shopify_s=([^;]+)/)?.[1] || "",
|
|
45
|
-
consent: cookie.match(/\b_tracking_consent=([^;]+)/)?.[1] || ""
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
return trackingValues;
|
|
49
|
-
}
|
|
50
|
-
function extractFromPerformanceEntry(entry, isConsentRequired = true) {
|
|
51
|
-
let uniqueToken = "";
|
|
52
|
-
let visitToken = "";
|
|
53
|
-
let consent = "";
|
|
54
|
-
const serverTiming = entry.serverTiming;
|
|
55
|
-
if (serverTiming && serverTiming.length >= 3) for (let i = serverTiming.length - 1; i >= 0; i--) {
|
|
56
|
-
const { name, description } = serverTiming[i];
|
|
57
|
-
if (!name || !description) continue;
|
|
58
|
-
if (name === "_y") uniqueToken = description;
|
|
59
|
-
else if (name === "_s") visitToken = description;
|
|
60
|
-
else if (name === "_cmp") consent = description;
|
|
61
|
-
if (uniqueToken && visitToken && consent) break;
|
|
62
|
-
}
|
|
63
|
-
return uniqueToken && visitToken && (isConsentRequired ? consent : true) ? {
|
|
64
|
-
uniqueToken,
|
|
65
|
-
visitToken,
|
|
66
|
-
consent
|
|
67
|
-
} : void 0;
|
|
15
|
+
const cookie = typeof arguments[0] === "string" ? arguments[0] : typeof document !== "undefined" ? document.cookie : "";
|
|
16
|
+
const customerPrivacy = typeof window === "undefined" ? void 0 : window.Shopify?.customerPrivacy;
|
|
17
|
+
const internal = customerPrivacy?.__internal;
|
|
18
|
+
const tokenOptions = {
|
|
19
|
+
generateFallback: customerPrivacy?.config?.asyncConsent === true,
|
|
20
|
+
tag: "hydrogen:classic"
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
uniqueToken: internal?.uniqueToken ? internal.uniqueToken(tokenOptions) ?? "" : cookie.match(/\b_shopify_y=([^;]+)/)?.[1] ?? "",
|
|
24
|
+
visitToken: internal?.visitToken ? internal.visitToken(tokenOptions) ?? "" : cookie.match(/\b_shopify_s=([^;]+)/)?.[1] ?? "",
|
|
25
|
+
consent: customerPrivacy?.cachedConsent ?? cookie.match(/\b_tracking_consent=([^;]+)/)?.[1] ?? ""
|
|
26
|
+
};
|
|
68
27
|
}
|
|
69
28
|
//#endregion
|
|
70
29
|
exports.SHOPIFY_UNIQUE_TOKEN_HEADER = SHOPIFY_UNIQUE_TOKEN_HEADER;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracking-utils.js","names":[],"sources":["../../src/tracking-utils.ts"],"sourcesContent":["/** Storefront API header for VisitToken */\nexport const SHOPIFY_VISIT_TOKEN_HEADER = 'X-Shopify-VisitToken';\n/** Storefront API header for UniqueToken */\nexport const SHOPIFY_UNIQUE_TOKEN_HEADER = 'X-Shopify-UniqueToken';\n\ntype TrackingValues = {\n /** Identifier for the unique user. Equivalent to the deprecated _shopify_y cookie */\n uniqueToken: string;\n /** Identifier for the current visit. Equivalent to the deprecated _shopify_s cookie */\n visitToken: string;\n /** Represents the consent given by the user or the default region consent configured in Admin */\n consent: string;\n};\n\n//
|
|
1
|
+
{"version":3,"file":"tracking-utils.js","names":[],"sources":["../../src/tracking-utils.ts"],"sourcesContent":["/** Storefront API header for VisitToken */\nexport const SHOPIFY_VISIT_TOKEN_HEADER = 'X-Shopify-VisitToken';\n/** Storefront API header for UniqueToken */\nexport const SHOPIFY_UNIQUE_TOKEN_HEADER = 'X-Shopify-UniqueToken';\n\ntype TrackingValues = {\n /** Identifier for the unique user. Equivalent to the deprecated _shopify_y cookie */\n uniqueToken: string;\n /** Identifier for the current visit. Equivalent to the deprecated _shopify_s cookie */\n visitToken: string;\n /** Represents the consent given by the user or the default region consent configured in Admin */\n consent: string;\n};\n\n// Keep the consent-tracking-api token interface out of Hydrogen's public\n// global types since it could change in the future.\ntype CustomerPrivacyWithTracking = {\n config?: {asyncConsent?: boolean};\n cachedConsent?: string;\n __internal?: {\n uniqueToken?: (options?: {\n generateFallback?: boolean;\n tag?: string;\n }) => string | undefined;\n visitToken?: (options?: {\n generateFallback?: boolean;\n tag?: string;\n }) => string | undefined;\n };\n};\n\n/**\n * Retrieves user session tracking values for analytics and marketing from the\n * browser environment. Customer Privacy API token readers are authoritative\n * when available, including when consent denies tracking. Deprecated\n * `_shopify_y`/`_shopify_s` cookies are read only without an API token reader.\n * Consent comes from CTA's cache or the legacy `_tracking_consent` cookie.\n * @publicDocs\n */\nexport function getTrackingValues(): TrackingValues {\n const cookie =\n // Read from arguments to avoid declaring parameters in this function signature.\n // This logic is only used internally from `getShopifyCookies` and will be deprecated.\n typeof arguments[0] === 'string'\n ? arguments[0]\n : typeof document !== 'undefined'\n ? document.cookie\n : '';\n\n const customerPrivacy =\n typeof window === 'undefined'\n ? undefined\n : (window as {Shopify?: {customerPrivacy?: CustomerPrivacyWithTracking}})\n .Shopify?.customerPrivacy;\n\n const internal = customerPrivacy?.__internal;\n // Async consent owns initialization and suppresses fallback generation until\n // it is loaded. Afterwards CTA can refresh expired tokens, as in preview.\n // Standalone hydrogen-react's explicit consent fetch keeps its previous policy.\n const tokenOptions = {\n generateFallback: customerPrivacy?.config?.asyncConsent === true,\n tag: 'hydrogen:classic',\n };\n\n return {\n // An installed CTA reader is authoritative, including undefined on denial.\n // Falling through to a legacy cookie could restore a disallowed token.\n uniqueToken: internal?.uniqueToken\n ? (internal.uniqueToken(tokenOptions) ?? '')\n : (cookie.match(/\\b_shopify_y=([^;]+)/)?.[1] ?? ''),\n visitToken: internal?.visitToken\n ? (internal.visitToken(tokenOptions) ?? '')\n : (cookie.match(/\\b_shopify_s=([^;]+)/)?.[1] ?? ''),\n consent:\n customerPrivacy?.cachedConsent ??\n cookie.match(/\\b_tracking_consent=([^;]+)/)?.[1] ??\n '',\n };\n}\n"],"mappings":";;AACA,IAAa,6BAA6B;;AAE1C,IAAa,8BAA8B;;;;;;;;;AAoC3C,SAAgB,oBAAoC;CAClD,MAAM,SAGJ,OAAO,UAAU,OAAO,WACpB,UAAU,KACV,OAAO,aAAa,cAClB,SAAS,SACT;CAER,MAAM,kBACJ,OAAO,WAAW,cACd,KAAA,IACC,OACE,SAAS;CAElB,MAAM,WAAW,iBAAiB;CAIlC,MAAM,eAAe;EACnB,kBAAkB,iBAAiB,QAAQ,iBAAiB;EAC5D,KAAK;EACN;AAED,QAAO;EAGL,aAAa,UAAU,cAClB,SAAS,YAAY,aAAa,IAAI,KACtC,OAAO,MAAM,uBAAuB,GAAG,MAAM;EAClD,YAAY,UAAU,aACjB,SAAS,WAAW,aAAa,IAAI,KACrC,OAAO,MAAM,uBAAuB,GAAG,MAAM;EAClD,SACE,iBAAiB,iBACjB,OAAO,MAAM,8BAA8B,GAAG,MAC9C;EACH"}
|
|
@@ -3,68 +3,27 @@
|
|
|
3
3
|
var SHOPIFY_VISIT_TOKEN_HEADER = "X-Shopify-VisitToken";
|
|
4
4
|
/** Storefront API header for UniqueToken */
|
|
5
5
|
var SHOPIFY_UNIQUE_TOKEN_HEADER = "X-Shopify-UniqueToken";
|
|
6
|
-
var cachedTrackingValues = { current: null };
|
|
7
6
|
/**
|
|
8
|
-
* Retrieves user session tracking values for analytics and marketing from the
|
|
7
|
+
* Retrieves user session tracking values for analytics and marketing from the
|
|
8
|
+
* browser environment. Customer Privacy API token readers are authoritative
|
|
9
|
+
* when available, including when consent denies tracking. Deprecated
|
|
10
|
+
* `_shopify_y`/`_shopify_s` cookies are read only without an API token reader.
|
|
11
|
+
* Consent comes from CTA's cache or the legacy `_tracking_consent` cookie.
|
|
9
12
|
* @publicDocs
|
|
10
13
|
*/
|
|
11
14
|
function getTrackingValues() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (matchedHost === currentHost || sfapiPath && matchedHost?.endsWith(`.${currentHost}`)) {
|
|
25
|
-
const values = extractFromPerformanceEntry(entry);
|
|
26
|
-
if (values) {
|
|
27
|
-
matchedValues = values;
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (matchedValues) trackingValues = matchedValues;
|
|
33
|
-
if (trackingValues) cachedTrackingValues.current = trackingValues;
|
|
34
|
-
else if (cachedTrackingValues.current) trackingValues = cachedTrackingValues.current;
|
|
35
|
-
if (!trackingValues) {
|
|
36
|
-
const navigationEntries = performance.getEntriesByType("navigation")[0];
|
|
37
|
-
trackingValues = extractFromPerformanceEntry(navigationEntries, false);
|
|
38
|
-
}
|
|
39
|
-
} catch {}
|
|
40
|
-
if (!trackingValues) {
|
|
41
|
-
const cookie = typeof arguments[0] === "string" ? arguments[0] : typeof document !== "undefined" ? document.cookie : "";
|
|
42
|
-
trackingValues = {
|
|
43
|
-
uniqueToken: cookie.match(/\b_shopify_y=([^;]+)/)?.[1] || "",
|
|
44
|
-
visitToken: cookie.match(/\b_shopify_s=([^;]+)/)?.[1] || "",
|
|
45
|
-
consent: cookie.match(/\b_tracking_consent=([^;]+)/)?.[1] || ""
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
return trackingValues;
|
|
49
|
-
}
|
|
50
|
-
function extractFromPerformanceEntry(entry, isConsentRequired = true) {
|
|
51
|
-
let uniqueToken = "";
|
|
52
|
-
let visitToken = "";
|
|
53
|
-
let consent = "";
|
|
54
|
-
const serverTiming = entry.serverTiming;
|
|
55
|
-
if (serverTiming && serverTiming.length >= 3) for (let i = serverTiming.length - 1; i >= 0; i--) {
|
|
56
|
-
const { name, description } = serverTiming[i];
|
|
57
|
-
if (!name || !description) continue;
|
|
58
|
-
if (name === "_y") uniqueToken = description;
|
|
59
|
-
else if (name === "_s") visitToken = description;
|
|
60
|
-
else if (name === "_cmp") consent = description;
|
|
61
|
-
if (uniqueToken && visitToken && consent) break;
|
|
62
|
-
}
|
|
63
|
-
return uniqueToken && visitToken && (isConsentRequired ? consent : true) ? {
|
|
64
|
-
uniqueToken,
|
|
65
|
-
visitToken,
|
|
66
|
-
consent
|
|
67
|
-
} : void 0;
|
|
15
|
+
const cookie = typeof arguments[0] === "string" ? arguments[0] : typeof document !== "undefined" ? document.cookie : "";
|
|
16
|
+
const customerPrivacy = typeof window === "undefined" ? void 0 : window.Shopify?.customerPrivacy;
|
|
17
|
+
const internal = customerPrivacy?.__internal;
|
|
18
|
+
const tokenOptions = {
|
|
19
|
+
generateFallback: customerPrivacy?.config?.asyncConsent === true,
|
|
20
|
+
tag: "hydrogen:classic"
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
uniqueToken: internal?.uniqueToken ? internal.uniqueToken(tokenOptions) ?? "" : cookie.match(/\b_shopify_y=([^;]+)/)?.[1] ?? "",
|
|
24
|
+
visitToken: internal?.visitToken ? internal.visitToken(tokenOptions) ?? "" : cookie.match(/\b_shopify_s=([^;]+)/)?.[1] ?? "",
|
|
25
|
+
consent: customerPrivacy?.cachedConsent ?? cookie.match(/\b_tracking_consent=([^;]+)/)?.[1] ?? ""
|
|
26
|
+
};
|
|
68
27
|
}
|
|
69
28
|
//#endregion
|
|
70
29
|
export { SHOPIFY_UNIQUE_TOKEN_HEADER, SHOPIFY_VISIT_TOKEN_HEADER, getTrackingValues };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracking-utils.mjs","names":[],"sources":["../../src/tracking-utils.ts"],"sourcesContent":["/** Storefront API header for VisitToken */\nexport const SHOPIFY_VISIT_TOKEN_HEADER = 'X-Shopify-VisitToken';\n/** Storefront API header for UniqueToken */\nexport const SHOPIFY_UNIQUE_TOKEN_HEADER = 'X-Shopify-UniqueToken';\n\ntype TrackingValues = {\n /** Identifier for the unique user. Equivalent to the deprecated _shopify_y cookie */\n uniqueToken: string;\n /** Identifier for the current visit. Equivalent to the deprecated _shopify_s cookie */\n visitToken: string;\n /** Represents the consent given by the user or the default region consent configured in Admin */\n consent: string;\n};\n\n//
|
|
1
|
+
{"version":3,"file":"tracking-utils.mjs","names":[],"sources":["../../src/tracking-utils.ts"],"sourcesContent":["/** Storefront API header for VisitToken */\nexport const SHOPIFY_VISIT_TOKEN_HEADER = 'X-Shopify-VisitToken';\n/** Storefront API header for UniqueToken */\nexport const SHOPIFY_UNIQUE_TOKEN_HEADER = 'X-Shopify-UniqueToken';\n\ntype TrackingValues = {\n /** Identifier for the unique user. Equivalent to the deprecated _shopify_y cookie */\n uniqueToken: string;\n /** Identifier for the current visit. Equivalent to the deprecated _shopify_s cookie */\n visitToken: string;\n /** Represents the consent given by the user or the default region consent configured in Admin */\n consent: string;\n};\n\n// Keep the consent-tracking-api token interface out of Hydrogen's public\n// global types since it could change in the future.\ntype CustomerPrivacyWithTracking = {\n config?: {asyncConsent?: boolean};\n cachedConsent?: string;\n __internal?: {\n uniqueToken?: (options?: {\n generateFallback?: boolean;\n tag?: string;\n }) => string | undefined;\n visitToken?: (options?: {\n generateFallback?: boolean;\n tag?: string;\n }) => string | undefined;\n };\n};\n\n/**\n * Retrieves user session tracking values for analytics and marketing from the\n * browser environment. Customer Privacy API token readers are authoritative\n * when available, including when consent denies tracking. Deprecated\n * `_shopify_y`/`_shopify_s` cookies are read only without an API token reader.\n * Consent comes from CTA's cache or the legacy `_tracking_consent` cookie.\n * @publicDocs\n */\nexport function getTrackingValues(): TrackingValues {\n const cookie =\n // Read from arguments to avoid declaring parameters in this function signature.\n // This logic is only used internally from `getShopifyCookies` and will be deprecated.\n typeof arguments[0] === 'string'\n ? arguments[0]\n : typeof document !== 'undefined'\n ? document.cookie\n : '';\n\n const customerPrivacy =\n typeof window === 'undefined'\n ? undefined\n : (window as {Shopify?: {customerPrivacy?: CustomerPrivacyWithTracking}})\n .Shopify?.customerPrivacy;\n\n const internal = customerPrivacy?.__internal;\n // Async consent owns initialization and suppresses fallback generation until\n // it is loaded. Afterwards CTA can refresh expired tokens, as in preview.\n // Standalone hydrogen-react's explicit consent fetch keeps its previous policy.\n const tokenOptions = {\n generateFallback: customerPrivacy?.config?.asyncConsent === true,\n tag: 'hydrogen:classic',\n };\n\n return {\n // An installed CTA reader is authoritative, including undefined on denial.\n // Falling through to a legacy cookie could restore a disallowed token.\n uniqueToken: internal?.uniqueToken\n ? (internal.uniqueToken(tokenOptions) ?? '')\n : (cookie.match(/\\b_shopify_y=([^;]+)/)?.[1] ?? ''),\n visitToken: internal?.visitToken\n ? (internal.visitToken(tokenOptions) ?? '')\n : (cookie.match(/\\b_shopify_s=([^;]+)/)?.[1] ?? ''),\n consent:\n customerPrivacy?.cachedConsent ??\n cookie.match(/\\b_tracking_consent=([^;]+)/)?.[1] ??\n '',\n };\n}\n"],"mappings":";;AACA,IAAa,6BAA6B;;AAE1C,IAAa,8BAA8B;;;;;;;;;AAoC3C,SAAgB,oBAAoC;CAClD,MAAM,SAGJ,OAAO,UAAU,OAAO,WACpB,UAAU,KACV,OAAO,aAAa,cAClB,SAAS,SACT;CAER,MAAM,kBACJ,OAAO,WAAW,cACd,KAAA,IACC,OACE,SAAS;CAElB,MAAM,WAAW,iBAAiB;CAIlC,MAAM,eAAe;EACnB,kBAAkB,iBAAiB,QAAQ,iBAAiB;EAC5D,KAAK;EACN;AAED,QAAO;EAGL,aAAa,UAAU,cAClB,SAAS,YAAY,aAAa,IAAI,KACtC,OAAO,MAAM,uBAAuB,GAAG,MAAM;EAClD,YAAY,UAAU,aACjB,SAAS,WAAW,aAAa,IAAI,KACrC,OAAO,MAAM,uBAAuB,GAAG,MAAM;EAClD,SACE,iBAAiB,iBACjB,OAAO,MAAM,8BAA8B,GAAG,MAC9C;EACH"}
|
|
@@ -1,85 +1,50 @@
|
|
|
1
1
|
require("./_virtual/_rolldown/runtime.js");
|
|
2
|
-
const require_cart_constants = require("./cart-constants.js");
|
|
3
2
|
const require_tracking_utils = require("./tracking-utils.js");
|
|
4
|
-
const require_cookies_utils = require("./cookies-utils.js");
|
|
5
3
|
let react = require("react");
|
|
6
|
-
let worktop_cookie = require("worktop/cookie");
|
|
7
4
|
//#region src/useShopifyCookies.tsx
|
|
8
|
-
var
|
|
9
|
-
var shortTermLength = 1800;
|
|
5
|
+
var CONSENT_MANAGEMENT_MARKER_HEADER = "Shopify-Storefront-Consent-Management";
|
|
10
6
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* Optionally refreshes backend-managed cookies for standalone integrations.
|
|
8
|
+
* The Customer Privacy API owns tracking values and legacy cookie expiration.
|
|
13
9
|
*
|
|
14
|
-
* If `fetchTrackingValues` is true,
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* For example, set it to `true` if you are using `hydrogen-react` only with
|
|
19
|
-
* a different framework and still need to make a same-domain request to
|
|
20
|
-
* Storefront API to set cookies.
|
|
10
|
+
* If `fetchTrackingValues` is true, this sends a consent request through the
|
|
11
|
+
* Storefront API proxy, retrying against `checkoutDomain` if provided. Hydrogen's
|
|
12
|
+
* built-in analytics already delegates consent initialization to the Customer
|
|
13
|
+
* Privacy API and does not use this hook.
|
|
21
14
|
*
|
|
22
|
-
*
|
|
23
|
-
* Useful when you only want to use the newer tracking values and not rely on the deprecated ones.
|
|
24
|
-
*
|
|
25
|
-
* @returns `true` when cookies are set and ready.
|
|
15
|
+
* @returns `true` when the consent request has settled and cookies are ready.
|
|
26
16
|
* @publicDocs
|
|
27
17
|
*/
|
|
28
18
|
function useShopifyCookies(options) {
|
|
29
|
-
const {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
fetchTrackingValues,
|
|
33
|
-
checkoutDomain
|
|
34
|
-
});
|
|
19
|
+
const { checkoutDomain, storefrontAccessToken, fetchTrackingValues = false } = options ?? {};
|
|
20
|
+
const [cookiesReady, setCookiesReady] = (0, react.useState)(!fetchTrackingValues);
|
|
21
|
+
const hasFetchedTrackingValues = (0, react.useRef)(false);
|
|
35
22
|
(0, react.useEffect)(() => {
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
*
|
|
40
|
-
* If no domain is provided, the cookie will be set for the current host.
|
|
41
|
-
* For Shopify, we need to ensure this domain is set with a leading dot.
|
|
42
|
-
*/
|
|
43
|
-
let currentDomain = domain || window.location.host;
|
|
44
|
-
if (checkoutDomain) {
|
|
45
|
-
const checkoutDomainParts = checkoutDomain.split(".").reverse();
|
|
46
|
-
const currentDomainParts = currentDomain.split(".").reverse();
|
|
47
|
-
const sameDomainParts = [];
|
|
48
|
-
checkoutDomainParts.forEach((part, index) => {
|
|
49
|
-
if (part === currentDomainParts[index]) sameDomainParts.push(part);
|
|
50
|
-
});
|
|
51
|
-
currentDomain = sameDomainParts.reverse().join(".");
|
|
52
|
-
}
|
|
53
|
-
if (/^localhost/.test(currentDomain)) currentDomain = "";
|
|
54
|
-
const domainWithLeadingDot = currentDomain ? /^\./.test(currentDomain) ? currentDomain : `.${currentDomain}` : "";
|
|
55
|
-
/**
|
|
56
|
-
* Set user and session cookies and refresh the expiry time
|
|
57
|
-
*/
|
|
58
|
-
if (hasUserConsent) {
|
|
59
|
-
const trackingValues = require_tracking_utils.getTrackingValues();
|
|
60
|
-
if ((trackingValues.uniqueToken || trackingValues.visitToken || "").startsWith("00000000-")) return;
|
|
61
|
-
setCookie(require_cart_constants.SHOPIFY_Y, trackingValues.uniqueToken || require_cookies_utils.buildUUID(), longTermLength, domainWithLeadingDot);
|
|
62
|
-
setCookie(require_cart_constants.SHOPIFY_S, trackingValues.visitToken || require_cookies_utils.buildUUID(), shortTermLength, domainWithLeadingDot);
|
|
63
|
-
} else {
|
|
64
|
-
setCookie(require_cart_constants.SHOPIFY_Y, "", 0, domainWithLeadingDot);
|
|
65
|
-
setCookie(require_cart_constants.SHOPIFY_S, "", 0, domainWithLeadingDot);
|
|
23
|
+
if (!fetchTrackingValues) {
|
|
24
|
+
setCookiesReady(true);
|
|
25
|
+
return;
|
|
66
26
|
}
|
|
27
|
+
if (hasFetchedTrackingValues.current) return;
|
|
28
|
+
hasFetchedTrackingValues.current = true;
|
|
29
|
+
const fetchConsentValues = async () => {
|
|
30
|
+
try {
|
|
31
|
+
return await fetchTrackingValuesFromBrowser(storefrontAccessToken);
|
|
32
|
+
} catch (sameOriginError) {
|
|
33
|
+
if (!checkoutDomain) throw sameOriginError;
|
|
34
|
+
return fetchTrackingValuesFromBrowser(storefrontAccessToken, checkoutDomain);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
fetchConsentValues().catch((error) => {
|
|
38
|
+
console.warn("[h2:warn:useShopifyCookies] Failed to fetch tracking values from browser: " + (error instanceof Error ? error.message : String(error)));
|
|
39
|
+
}).finally(() => {
|
|
40
|
+
setCookiesReady(true);
|
|
41
|
+
});
|
|
67
42
|
}, [
|
|
68
|
-
coreCookiesReady,
|
|
69
|
-
hasUserConsent,
|
|
70
|
-
domain,
|
|
71
43
|
checkoutDomain,
|
|
72
|
-
|
|
44
|
+
fetchTrackingValues,
|
|
45
|
+
storefrontAccessToken
|
|
73
46
|
]);
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
function setCookie(name, value, maxage, domain) {
|
|
77
|
-
document.cookie = (0, worktop_cookie.stringify)(name, value, {
|
|
78
|
-
maxage,
|
|
79
|
-
domain,
|
|
80
|
-
samesite: "Lax",
|
|
81
|
-
path: "/"
|
|
82
|
-
});
|
|
47
|
+
return cookiesReady;
|
|
83
48
|
}
|
|
84
49
|
async function fetchTrackingValuesFromBrowser(storefrontAccessToken, storefrontApiDomain = "") {
|
|
85
50
|
const { uniqueToken, visitToken } = require_tracking_utils.getTrackingValues();
|
|
@@ -88,43 +53,15 @@ async function fetchTrackingValuesFromBrowser(storefrontAccessToken, storefrontA
|
|
|
88
53
|
headers: {
|
|
89
54
|
"Content-Type": "application/json",
|
|
90
55
|
...storefrontAccessToken && { "X-Shopify-Storefront-Access-Token": storefrontAccessToken },
|
|
56
|
+
...storefrontApiDomain ? void 0 : { [CONSENT_MANAGEMENT_MARKER_HEADER]: "1" },
|
|
91
57
|
...visitToken || uniqueToken ? {
|
|
92
58
|
[require_tracking_utils.SHOPIFY_VISIT_TOKEN_HEADER]: visitToken,
|
|
93
59
|
[require_tracking_utils.SHOPIFY_UNIQUE_TOKEN_HEADER]: uniqueToken
|
|
94
60
|
} : void 0
|
|
95
61
|
},
|
|
96
|
-
body: JSON.stringify({ query: "query ensureCookies { consentManagement { cookies(visitorConsent:{}) { cookieDomain } } }" })
|
|
62
|
+
body: JSON.stringify({ query: "query ensureCookies { consentManagement { cookies(visitorConsent:{}) { trackingConsentCookie cookieDomain shopifyUnique shopifyVisit } } }" })
|
|
97
63
|
});
|
|
98
64
|
if (!response.ok) throw new Error(`Failed to fetch consent from browser: ${response.status} ${response.statusText}`);
|
|
99
|
-
await response.json();
|
|
100
|
-
require_tracking_utils.getTrackingValues();
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Gets http-only cookies from Storefront API via same-origin fetch request.
|
|
104
|
-
* Falls back to checkout domain if provided to at least obtain the tracking
|
|
105
|
-
* values via server-timing headers.
|
|
106
|
-
*/
|
|
107
|
-
function useCoreShopifyCookies({ checkoutDomain, storefrontAccessToken, fetchTrackingValues = false }) {
|
|
108
|
-
const [cookiesReady, setCookiesReady] = (0, react.useState)(!fetchTrackingValues);
|
|
109
|
-
const hasFetchedTrackingValues = (0, react.useRef)(false);
|
|
110
|
-
(0, react.useEffect)(() => {
|
|
111
|
-
if (!fetchTrackingValues) {
|
|
112
|
-
setCookiesReady(true);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
if (hasFetchedTrackingValues.current) return;
|
|
116
|
-
hasFetchedTrackingValues.current = true;
|
|
117
|
-
fetchTrackingValuesFromBrowser(storefrontAccessToken).catch((error) => checkoutDomain ? fetchTrackingValuesFromBrowser(storefrontAccessToken, checkoutDomain) : Promise.reject(error)).catch((error) => {
|
|
118
|
-
console.warn("[h2:warn:useShopifyCookies] Failed to fetch tracking values from browser: " + (error instanceof Error ? error.message : String(error)));
|
|
119
|
-
}).finally(() => {
|
|
120
|
-
setCookiesReady(true);
|
|
121
|
-
});
|
|
122
|
-
}, [
|
|
123
|
-
checkoutDomain,
|
|
124
|
-
fetchTrackingValues,
|
|
125
|
-
storefrontAccessToken
|
|
126
|
-
]);
|
|
127
|
-
return cookiesReady;
|
|
128
65
|
}
|
|
129
66
|
//#endregion
|
|
130
67
|
exports.useShopifyCookies = useShopifyCookies;
|