@wapitee/typhoonx-hydrogen 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,11 +42,12 @@ const {nonce, header, NonceProvider} = createContentSecurityPolicy({
42
42
 
43
43
  ### Props
44
44
 
45
- | Prop | Type | Required | Description |
46
- | -------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
47
- | `merchantId` | `string` | yes | TyphoonX merchant ID (`TPX-…`) |
48
- | `shopId` | `string` | yes | Shopify store ID |
49
- | `cookieDomain` | `string` | no | Cookie `Domain` for a first-party client id. Defaults to the current hostname's apex domain (e.g. `.example.com`) |
45
+ | Prop | Type | Required | Description |
46
+ | --------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
47
+ | `merchantId` | `string` | yes | TyphoonX merchant ID (`TPX-…`) |
48
+ | `shopId` | `string` | yes | Shopify store ID |
49
+ | `cookieDomain` | `string` | no | Cookie `Domain` for a first-party client id. Defaults to the current hostname's apex domain (e.g. `.example.com`) |
50
+ | `measurementId` | `string` | no | GA4 measurement ID (`G-…`). Enables `ga_session_id` |
50
51
 
51
52
  ## License
52
53
 
@@ -2,6 +2,8 @@ export interface TyphoonXProps {
2
2
  merchantId: string;
3
3
  shopId: string;
4
4
  cookieDomain?: string;
5
+ /** GA4 measurement ID (`G-…`) whose `_ga_<ID>` cookie supplies `ga_session_id`. */
6
+ measurementId?: string;
5
7
  }
6
8
  export default function TyphoonX(props: TyphoonXProps): import("react").JSX.Element | null;
7
9
  //# sourceMappingURL=TyphoonX.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TyphoonX.d.ts","sourceRoot":"","sources":["../src/TyphoonX.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAmCD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAK,EAAE,aAAa,sCAqBpD"}
1
+ {"version":3,"file":"TyphoonX.d.ts","sourceRoot":"","sources":["../src/TyphoonX.tsx"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAmCD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAK,EAAE,aAAa,sCAuBpD"}
package/dist/TyphoonX.js CHANGED
@@ -2,6 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { flattenConnection, parseGid, useAnalytics } from '@shopify/hydrogen';
3
3
  import { useEffect, useRef, useState } from 'react';
4
4
  import { getOrCreateClientId, hasClientId } from './client-id.js';
5
+ import { getGoogleIds } from './google-ids.js';
6
+ import { getMetaPixelIds } from './meta-pixel.js';
5
7
  const COLLECT_ENDPOINT = 'https://spell.typhoonx.io/api/v1/receive';
6
8
  export default function TyphoonX(props) {
7
9
  const { subscribe } = useAnalytics();
@@ -20,7 +22,7 @@ export default function TyphoonX(props) {
20
22
  }
21
23
  return _jsx(TyphoonXClient, { ...props });
22
24
  }
23
- function TyphoonXClient({ cookieDomain, merchantId, shopId }) {
25
+ function TyphoonXClient({ cookieDomain, measurementId, merchantId, shopId, }) {
24
26
  const { canTrack, register, subscribe } = useAnalytics();
25
27
  const { ready } = register('TyphoonX');
26
28
  const currentUrlRef = useRef(null);
@@ -59,6 +61,8 @@ function TyphoonXClient({ cookieDomain, merchantId, shopId }) {
59
61
  timestamp: new Date().toISOString(),
60
62
  user_agent: window.navigator.userAgent,
61
63
  ...(currency === undefined ? {} : { currency }),
64
+ ...getMetaPixelIds(url),
65
+ ...getGoogleIds(url, measurementId),
62
66
  });
63
67
  subscribe('cart_viewed', (data) => {
64
68
  const { cart } = data;
@@ -149,8 +153,8 @@ function TyphoonXClient({ cookieDomain, merchantId, shopId }) {
149
153
  quantity,
150
154
  },
151
155
  ],
152
- value: String(Number(prevLine.cost.totalAmount.amount)
153
- - Number(currentLine?.cost.totalAmount.amount ?? 0)),
156
+ value: String(Number(prevLine.cost.totalAmount.amount) -
157
+ Number(currentLine?.cost.totalAmount.amount ?? 0)),
154
158
  });
155
159
  });
156
160
  subscribe('product_viewed', (data) => {
@@ -183,6 +187,14 @@ function TyphoonXClient({ cookieDomain, merchantId, shopId }) {
183
187
  });
184
188
  });
185
189
  ready();
186
- }, [cookieDomain, merchantId, shopId, canTrack, ready, subscribe]);
190
+ }, [
191
+ cookieDomain,
192
+ measurementId,
193
+ merchantId,
194
+ shopId,
195
+ canTrack,
196
+ ready,
197
+ subscribe,
198
+ ]);
187
199
  return null;
188
200
  }
@@ -0,0 +1,13 @@
1
+ export interface GoogleIds {
2
+ ga_client_id?: string | undefined;
3
+ ga_session_id?: string | undefined;
4
+ gbraid?: string | undefined;
5
+ gclid?: string | undefined;
6
+ wbraid?: string | undefined;
7
+ }
8
+ /**
9
+ * GA4 client and session IDs from `_ga` / `_ga_<ID>`, and Google Ads click IDs
10
+ * from `_gcl_aw` falling back to `url`'s `gclid`, `gbraid` and `wbraid`.
11
+ */
12
+ export declare function getGoogleIds(url: string, measurementId?: string): GoogleIds;
13
+ //# sourceMappingURL=google-ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-ids.d.ts","sourceRoot":"","sources":["../src/google-ids.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,SAAS;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAgB3E"}
@@ -0,0 +1,29 @@
1
+ import CookieLib from 'universal-cookie';
2
+ // Runtime default export is the class.
3
+ const cookies = new CookieLib();
4
+ /**
5
+ * GA4 client and session IDs from `_ga` / `_ga_<ID>`, and Google Ads click IDs
6
+ * from `_gcl_aw` falling back to `url`'s `gclid`, `gbraid` and `wbraid`.
7
+ */
8
+ export function getGoogleIds(url, measurementId) {
9
+ const params = searchParams(url);
10
+ const cookie = (name) => cookies.get(name, { doNotParse: true });
11
+ const param = (name) => params?.get(name)?.match(/^.+$/)?.[0];
12
+ return {
13
+ ga_client_id: cookie('_ga')?.match(/^GA\d\.\d+\.(.+)$/)?.[1],
14
+ ga_session_id: measurementId
15
+ ? cookie(`_ga_${measurementId.replace(/^G-/, '')}`)?.match(/^GS\d\.\d+\.s?(\d+)/)?.[1]
16
+ : undefined,
17
+ gbraid: param('gbraid'),
18
+ gclid: cookie('_gcl_aw')?.match(/^GCL\.\d+\.(.+)$/)?.[1] ?? param('gclid'),
19
+ wbraid: param('wbraid'),
20
+ };
21
+ }
22
+ function searchParams(url) {
23
+ try {
24
+ return new URL(url).searchParams;
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
@@ -0,0 +1,7 @@
1
+ export interface MetaPixelIds {
2
+ fbc?: string;
3
+ fbp?: string;
4
+ }
5
+ /** Meta Pixel `_fbp` / `_fbc` cookies, with `_fbc` falling back to `url`'s `fbclid`. */
6
+ export declare function getMetaPixelIds(url: string): MetaPixelIds;
7
+ //# sourceMappingURL=meta-pixel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-pixel.d.ts","sourceRoot":"","sources":["../src/meta-pixel.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAQzD"}
@@ -0,0 +1,23 @@
1
+ import CookieLib from 'universal-cookie';
2
+ // Runtime default export is the class.
3
+ const cookies = new CookieLib();
4
+ /** Meta Pixel `_fbp` / `_fbc` cookies, with `_fbc` falling back to `url`'s `fbclid`. */
5
+ export function getMetaPixelIds(url) {
6
+ const fbp = cookies.get('_fbp', { doNotParse: true });
7
+ const fbc = cookies.get('_fbc', { doNotParse: true }) ?? fbcFromUrl(url);
8
+ return {
9
+ ...(fbc === undefined ? {} : { fbc }),
10
+ ...(fbp === undefined ? {} : { fbp }),
11
+ };
12
+ }
13
+ function fbcFromUrl(url) {
14
+ let fbclid;
15
+ try {
16
+ fbclid = new URL(url).searchParams.get('fbclid');
17
+ }
18
+ catch {
19
+ return undefined;
20
+ }
21
+ // Meta specifies subdomain index 1 for an `_fbc` built outside the Pixel.
22
+ return fbclid ? `fb.1.${String(Date.now())}.${fbclid}` : undefined;
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wapitee/typhoonx-hydrogen",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "TyphoonX Hydrogen Analytics subscriber",
5
5
  "keywords": [
6
6
  "typhoonx",
@@ -10,14 +10,14 @@
10
10
  "react",
11
11
  "storefront"
12
12
  ],
13
- "homepage": "https://github.com/Wapitee-Interactive-Marketing-Limited/typhoonx-js/tree/main/packages/typhoonx-hydrogen",
13
+ "homepage": "https://github.com/Wapitee-Interactive-Marketing-Limited/typhoonx-js/tree/main/packages/hydrogen",
14
14
  "bugs": {
15
15
  "url": "https://github.com/Wapitee-Interactive-Marketing-Limited/typhoonx-js/issues"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "git+https://github.com/Wapitee-Interactive-Marketing-Limited/typhoonx-js.git",
20
- "directory": "packages/typhoonx-hydrogen"
20
+ "directory": "packages/hydrogen"
21
21
  },
22
22
  "license": "MIT",
23
23
  "author": "jay@wapitee.io",