@shware/analytics 11.6.0 → 11.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.
Files changed (52) hide show
  1. package/README.md +61 -0
  2. package/dist/ads/index.cjs +9 -0
  3. package/dist/ads/index.d.cts +4 -0
  4. package/dist/ads/index.d.mts +4 -0
  5. package/dist/ads/index.mjs +3 -0
  6. package/dist/ads/meta.cjs +234 -0
  7. package/dist/ads/meta.cjs.map +1 -0
  8. package/dist/ads/meta.d.cts +48 -0
  9. package/dist/ads/meta.d.cts.map +1 -0
  10. package/dist/ads/meta.d.mts +48 -0
  11. package/dist/ads/meta.d.mts.map +1 -0
  12. package/dist/ads/meta.mjs +232 -0
  13. package/dist/ads/meta.mjs.map +1 -0
  14. package/dist/ads/time.cjs +59 -0
  15. package/dist/ads/time.cjs.map +1 -0
  16. package/dist/ads/time.d.cts +17 -0
  17. package/dist/ads/time.d.cts.map +1 -0
  18. package/dist/ads/time.d.mts +17 -0
  19. package/dist/ads/time.d.mts.map +1 -0
  20. package/dist/ads/time.mjs +55 -0
  21. package/dist/ads/time.mjs.map +1 -0
  22. package/dist/ads/types.cjs +0 -0
  23. package/dist/ads/types.d.cts +57 -0
  24. package/dist/ads/types.d.cts.map +1 -0
  25. package/dist/ads/types.d.mts +57 -0
  26. package/dist/ads/types.d.mts.map +1 -0
  27. package/dist/ads/types.mjs +1 -0
  28. package/dist/native/deep-link.cjs +75 -0
  29. package/dist/native/deep-link.cjs.map +1 -0
  30. package/dist/native/deep-link.d.cts +8 -0
  31. package/dist/native/deep-link.d.cts.map +1 -0
  32. package/dist/native/deep-link.d.mts +8 -0
  33. package/dist/native/deep-link.d.mts.map +1 -0
  34. package/dist/native/deep-link.mjs +74 -0
  35. package/dist/native/deep-link.mjs.map +1 -0
  36. package/dist/native/index.cjs +2 -0
  37. package/dist/native/index.d.cts +2 -1
  38. package/dist/native/index.d.mts +2 -1
  39. package/dist/native/index.mjs +2 -1
  40. package/dist/native/setup.cjs +4 -2
  41. package/dist/native/setup.cjs.map +1 -1
  42. package/dist/native/setup.mjs +4 -2
  43. package/dist/native/setup.mjs.map +1 -1
  44. package/dist/setup/index.cjs +8 -1
  45. package/dist/setup/index.cjs.map +1 -1
  46. package/dist/setup/index.d.cts +14 -0
  47. package/dist/setup/index.d.cts.map +1 -1
  48. package/dist/setup/index.d.mts +14 -0
  49. package/dist/setup/index.d.mts.map +1 -1
  50. package/dist/setup/index.mjs +8 -1
  51. package/dist/setup/index.mjs.map +1 -1
  52. package/package.json +11 -1
@@ -0,0 +1,75 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let react_native = require("react-native");
3
+ let react_native_url_polyfill = require("react-native-url-polyfill");
4
+ //#region src/native/deep-link.ts
5
+ /**
6
+ * The link that opened the app for this visit, the app's landing page: `getTags` merges its URL
7
+ * (as `page_location`) and utm into every event's tags, so the session it starts is
8
+ * classified as a web page's URL would be. A universal link or an app link from an email or an ad
9
+ * opens the app rather than the site, and without this every one of those sessions was direct.
10
+ *
11
+ * The visit lasts from the open to the app going to the background, so every event in between
12
+ * carries the link, as every event of a web page carries that page's query; the next open, with a
13
+ * link or without, starts from nothing. Only the event that starts a session gets it classified:
14
+ * a link tapped while the session is still running joins it, as GA4 keeps one session across a
15
+ * change of campaign.
16
+ *
17
+ * Read from React Native's `Linking`: the URL that launched the process, and each one that brings
18
+ * the running app to the front. Pass it to `setupAnalytics({ deepLink })`, which starts the
19
+ * listening; nothing happens at import.
20
+ */
21
+ let openUrl;
22
+ /**
23
+ * The parameters a deep link carries: the utm its sender tagged it with. An ad platform's click id
24
+ * rides on the web landing page, not on a link into the app.
25
+ */
26
+ const UTM_KEYS = [
27
+ "utm_source",
28
+ "utm_medium",
29
+ "utm_campaign",
30
+ "utm_term",
31
+ "utm_content",
32
+ "utm_id",
33
+ "utm_source_platform",
34
+ "utm_creative_format",
35
+ "utm_marketing_tactic"
36
+ ];
37
+ let initialUrlPromise;
38
+ let listening = false;
39
+ /** The URL that launched the process, read once; a link that arrived since has the last word. */
40
+ function resolveInitialUrl() {
41
+ initialUrlPromise ??= react_native.Linking.getInitialURL().then((url) => {
42
+ if (url && openUrl === void 0) openUrl = url;
43
+ }, () => void 0);
44
+ return initialUrlPromise;
45
+ }
46
+ const deepLink = {
47
+ listen() {
48
+ if (listening) return;
49
+ listening = true;
50
+ react_native.Linking.addEventListener("url", ({ url }) => deepLink.open(url));
51
+ react_native.AppState.addEventListener("change", (state) => {
52
+ if (state === "background") openUrl = void 0;
53
+ });
54
+ },
55
+ /** Waits for the launch URL, so the first event of a launch has it. */
56
+ async getTags() {
57
+ await resolveInitialUrl();
58
+ if (!openUrl) return {};
59
+ const at = openUrl.indexOf("?");
60
+ const params = new react_native_url_polyfill.URLSearchParams(at === -1 ? "" : openUrl.slice(at + 1).split("#")[0]);
61
+ const tags = { page_location: openUrl };
62
+ for (const key of UTM_KEYS) {
63
+ const value = params.get(key);
64
+ if (value !== null) tags[key] = value;
65
+ }
66
+ return tags;
67
+ },
68
+ open(url) {
69
+ openUrl = url || void 0;
70
+ }
71
+ };
72
+ //#endregion
73
+ exports.deepLink = deepLink;
74
+
75
+ //# sourceMappingURL=deep-link.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-link.cjs","names":["Linking","URLSearchParams"],"sources":["../../src/native/deep-link.ts"],"sourcesContent":["import { AppState, Linking } from 'react-native';\nimport { URLSearchParams } from 'react-native-url-polyfill';\nimport type { DeepLink } from '../setup/index';\nimport type { TrackTags, UTMParams } from '../track/types';\n\n/**\n * The link that opened the app for this visit, the app's landing page: `getTags` merges its URL\n * (as `page_location`) and utm into every event's tags, so the session it starts is\n * classified as a web page's URL would be. A universal link or an app link from an email or an ad\n * opens the app rather than the site, and without this every one of those sessions was direct.\n *\n * The visit lasts from the open to the app going to the background, so every event in between\n * carries the link, as every event of a web page carries that page's query; the next open, with a\n * link or without, starts from nothing. Only the event that starts a session gets it classified:\n * a link tapped while the session is still running joins it, as GA4 keeps one session across a\n * change of campaign.\n *\n * Read from React Native's `Linking`: the URL that launched the process, and each one that brings\n * the running app to the front. Pass it to `setupAnalytics({ deepLink })`, which starts the\n * listening; nothing happens at import.\n */\nlet openUrl: string | undefined;\n\n/**\n * The parameters a deep link carries: the utm its sender tagged it with. An ad platform's click id\n * rides on the web landing page, not on a link into the app.\n */\nconst UTM_KEYS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n 'utm_id',\n 'utm_source_platform',\n 'utm_creative_format',\n 'utm_marketing_tactic',\n] as const satisfies readonly (keyof UTMParams)[];\nlet initialUrlPromise: Promise<void> | undefined;\nlet listening = false;\n\n/** The URL that launched the process, read once; a link that arrived since has the last word. */\nfunction resolveInitialUrl(): Promise<void> {\n initialUrlPromise ??= Linking.getInitialURL().then(\n (url) => {\n if (url && openUrl === undefined) openUrl = url;\n },\n () => undefined\n );\n return initialUrlPromise;\n}\n\nexport const deepLink: DeepLink & {\n /** The link this visit opened with, for an entry `Linking` does not see, such as a push notification. */\n open: (url: string | null | undefined) => void;\n} = {\n listen() {\n if (listening) return;\n listening = true;\n Linking.addEventListener('url', ({ url }) => deepLink.open(url));\n // `background`, not `inactive`: iOS goes inactive for a system sheet or the control center,\n // with the visit still on.\n AppState.addEventListener('change', (state) => {\n if (state === 'background') openUrl = undefined;\n });\n },\n /** Waits for the launch URL, so the first event of a launch has it. */\n async getTags(): Promise<TrackTags> {\n await resolveInitialUrl();\n if (!openUrl) return {};\n const at = openUrl.indexOf('?');\n const params = new URLSearchParams(at === -1 ? '' : openUrl.slice(at + 1).split('#')[0]);\n const tags: TrackTags = { page_location: openUrl };\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value !== null) tags[key] = value;\n }\n return tags;\n },\n open(url) {\n openUrl = url || undefined;\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,IAAI;;;;;AAMJ,MAAM,WAAW;CACf;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AACA,IAAI;AACJ,IAAI,YAAY;;AAGhB,SAAS,oBAAmC;CAC1C,sBAAsBA,aAAAA,QAAQ,cAAc,CAAC,CAAC,MAC3C,QAAQ;EACP,IAAI,OAAO,YAAY,KAAA,GAAW,UAAU;CAC9C,SACM,KAAA,CACR;CACA,OAAO;AACT;AAEA,MAAa,WAGT;CACF,SAAS;EACP,IAAI,WAAW;EACf,YAAY;EACZ,aAAA,QAAQ,iBAAiB,QAAQ,EAAE,UAAU,SAAS,KAAK,GAAG,CAAC;EAG/D,aAAA,SAAS,iBAAiB,WAAW,UAAU;GAC7C,IAAI,UAAU,cAAc,UAAU,KAAA;EACxC,CAAC;CACH;;CAEA,MAAM,UAA8B;EAClC,MAAM,kBAAkB;EACxB,IAAI,CAAC,SAAS,OAAO,CAAC;EACtB,MAAM,KAAK,QAAQ,QAAQ,GAAG;EAC9B,MAAM,SAAS,IAAIC,0BAAAA,gBAAgB,OAAO,KAAK,KAAK,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;EACvF,MAAM,OAAkB,EAAE,eAAe,QAAQ;EACjD,KAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,QAAQ,OAAO,IAAI,GAAG;GAC5B,IAAI,UAAU,MAAM,KAAK,OAAO;EAClC;EACA,OAAO;CACT;CACA,KAAK,KAAK;EACR,UAAU,OAAO,KAAA;CACnB;AACF"}
@@ -0,0 +1,8 @@
1
+ import { DeepLink } from "../setup/index.cjs";
2
+ //#region src/native/deep-link.d.ts
3
+ export declare const deepLink: DeepLink & {
4
+ /** The link this visit opened with, for an entry `Linking` does not see, such as a push notification. */
5
+ open: (url: string | null | undefined) => void;
6
+ };
7
+ //#endregion
8
+ //# sourceMappingURL=deep-link.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-link.d.cts","names":[],"sources":["../../src/native/deep-link.ts"],"mappings":";;qBAoDa,UAAU;;EAErB,OAAO"}
@@ -0,0 +1,8 @@
1
+ import { DeepLink } from "../setup/index.mjs";
2
+ //#region src/native/deep-link.d.ts
3
+ export declare const deepLink: DeepLink & {
4
+ /** The link this visit opened with, for an entry `Linking` does not see, such as a push notification. */
5
+ open: (url: string | null | undefined) => void;
6
+ };
7
+ //#endregion
8
+ //# sourceMappingURL=deep-link.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-link.d.mts","names":[],"sources":["../../src/native/deep-link.ts"],"mappings":";;qBAoDa,UAAU;;EAErB,OAAO"}
@@ -0,0 +1,74 @@
1
+ import { AppState, Linking } from "react-native";
2
+ import { URLSearchParams } from "react-native-url-polyfill";
3
+ //#region src/native/deep-link.ts
4
+ /**
5
+ * The link that opened the app for this visit, the app's landing page: `getTags` merges its URL
6
+ * (as `page_location`) and utm into every event's tags, so the session it starts is
7
+ * classified as a web page's URL would be. A universal link or an app link from an email or an ad
8
+ * opens the app rather than the site, and without this every one of those sessions was direct.
9
+ *
10
+ * The visit lasts from the open to the app going to the background, so every event in between
11
+ * carries the link, as every event of a web page carries that page's query; the next open, with a
12
+ * link or without, starts from nothing. Only the event that starts a session gets it classified:
13
+ * a link tapped while the session is still running joins it, as GA4 keeps one session across a
14
+ * change of campaign.
15
+ *
16
+ * Read from React Native's `Linking`: the URL that launched the process, and each one that brings
17
+ * the running app to the front. Pass it to `setupAnalytics({ deepLink })`, which starts the
18
+ * listening; nothing happens at import.
19
+ */
20
+ let openUrl;
21
+ /**
22
+ * The parameters a deep link carries: the utm its sender tagged it with. An ad platform's click id
23
+ * rides on the web landing page, not on a link into the app.
24
+ */
25
+ const UTM_KEYS = [
26
+ "utm_source",
27
+ "utm_medium",
28
+ "utm_campaign",
29
+ "utm_term",
30
+ "utm_content",
31
+ "utm_id",
32
+ "utm_source_platform",
33
+ "utm_creative_format",
34
+ "utm_marketing_tactic"
35
+ ];
36
+ let initialUrlPromise;
37
+ let listening = false;
38
+ /** The URL that launched the process, read once; a link that arrived since has the last word. */
39
+ function resolveInitialUrl() {
40
+ initialUrlPromise ??= Linking.getInitialURL().then((url) => {
41
+ if (url && openUrl === void 0) openUrl = url;
42
+ }, () => void 0);
43
+ return initialUrlPromise;
44
+ }
45
+ const deepLink = {
46
+ listen() {
47
+ if (listening) return;
48
+ listening = true;
49
+ Linking.addEventListener("url", ({ url }) => deepLink.open(url));
50
+ AppState.addEventListener("change", (state) => {
51
+ if (state === "background") openUrl = void 0;
52
+ });
53
+ },
54
+ /** Waits for the launch URL, so the first event of a launch has it. */
55
+ async getTags() {
56
+ await resolveInitialUrl();
57
+ if (!openUrl) return {};
58
+ const at = openUrl.indexOf("?");
59
+ const params = new URLSearchParams(at === -1 ? "" : openUrl.slice(at + 1).split("#")[0]);
60
+ const tags = { page_location: openUrl };
61
+ for (const key of UTM_KEYS) {
62
+ const value = params.get(key);
63
+ if (value !== null) tags[key] = value;
64
+ }
65
+ return tags;
66
+ },
67
+ open(url) {
68
+ openUrl = url || void 0;
69
+ }
70
+ };
71
+ //#endregion
72
+ export { deepLink };
73
+
74
+ //# sourceMappingURL=deep-link.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-link.mjs","names":[],"sources":["../../src/native/deep-link.ts"],"sourcesContent":["import { AppState, Linking } from 'react-native';\nimport { URLSearchParams } from 'react-native-url-polyfill';\nimport type { DeepLink } from '../setup/index';\nimport type { TrackTags, UTMParams } from '../track/types';\n\n/**\n * The link that opened the app for this visit, the app's landing page: `getTags` merges its URL\n * (as `page_location`) and utm into every event's tags, so the session it starts is\n * classified as a web page's URL would be. A universal link or an app link from an email or an ad\n * opens the app rather than the site, and without this every one of those sessions was direct.\n *\n * The visit lasts from the open to the app going to the background, so every event in between\n * carries the link, as every event of a web page carries that page's query; the next open, with a\n * link or without, starts from nothing. Only the event that starts a session gets it classified:\n * a link tapped while the session is still running joins it, as GA4 keeps one session across a\n * change of campaign.\n *\n * Read from React Native's `Linking`: the URL that launched the process, and each one that brings\n * the running app to the front. Pass it to `setupAnalytics({ deepLink })`, which starts the\n * listening; nothing happens at import.\n */\nlet openUrl: string | undefined;\n\n/**\n * The parameters a deep link carries: the utm its sender tagged it with. An ad platform's click id\n * rides on the web landing page, not on a link into the app.\n */\nconst UTM_KEYS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n 'utm_id',\n 'utm_source_platform',\n 'utm_creative_format',\n 'utm_marketing_tactic',\n] as const satisfies readonly (keyof UTMParams)[];\nlet initialUrlPromise: Promise<void> | undefined;\nlet listening = false;\n\n/** The URL that launched the process, read once; a link that arrived since has the last word. */\nfunction resolveInitialUrl(): Promise<void> {\n initialUrlPromise ??= Linking.getInitialURL().then(\n (url) => {\n if (url && openUrl === undefined) openUrl = url;\n },\n () => undefined\n );\n return initialUrlPromise;\n}\n\nexport const deepLink: DeepLink & {\n /** The link this visit opened with, for an entry `Linking` does not see, such as a push notification. */\n open: (url: string | null | undefined) => void;\n} = {\n listen() {\n if (listening) return;\n listening = true;\n Linking.addEventListener('url', ({ url }) => deepLink.open(url));\n // `background`, not `inactive`: iOS goes inactive for a system sheet or the control center,\n // with the visit still on.\n AppState.addEventListener('change', (state) => {\n if (state === 'background') openUrl = undefined;\n });\n },\n /** Waits for the launch URL, so the first event of a launch has it. */\n async getTags(): Promise<TrackTags> {\n await resolveInitialUrl();\n if (!openUrl) return {};\n const at = openUrl.indexOf('?');\n const params = new URLSearchParams(at === -1 ? '' : openUrl.slice(at + 1).split('#')[0]);\n const tags: TrackTags = { page_location: openUrl };\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value !== null) tags[key] = value;\n }\n return tags;\n },\n open(url) {\n openUrl = url || undefined;\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,IAAI;;;;;AAMJ,MAAM,WAAW;CACf;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AACA,IAAI;AACJ,IAAI,YAAY;;AAGhB,SAAS,oBAAmC;CAC1C,sBAAsB,QAAQ,cAAc,CAAC,CAAC,MAC3C,QAAQ;EACP,IAAI,OAAO,YAAY,KAAA,GAAW,UAAU;CAC9C,SACM,KAAA,CACR;CACA,OAAO;AACT;AAEA,MAAa,WAGT;CACF,SAAS;EACP,IAAI,WAAW;EACf,YAAY;EACZ,QAAQ,iBAAiB,QAAQ,EAAE,UAAU,SAAS,KAAK,GAAG,CAAC;EAG/D,SAAS,iBAAiB,WAAW,UAAU;GAC7C,IAAI,UAAU,cAAc,UAAU,KAAA;EACxC,CAAC;CACH;;CAEA,MAAM,UAA8B;EAClC,MAAM,kBAAkB;EACxB,IAAI,CAAC,SAAS,OAAO,CAAC;EACtB,MAAM,KAAK,QAAQ,QAAQ,GAAG;EAC9B,MAAM,SAAS,IAAI,gBAAgB,OAAO,KAAK,KAAK,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;EACvF,MAAM,OAAkB,EAAE,eAAe,QAAQ;EACjD,KAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,QAAQ,OAAO,IAAI,GAAG;GAC5B,IAAI,UAAU,MAAM,KAAK,OAAO;EAClC;EACA,OAAO;CACT;CACA,KAAK,KAAK;EACR,UAAU,OAAO,KAAA;CACnB;AACF"}
@@ -1,7 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_hooks_use_app_analytics = require("../hooks/use-app-analytics.cjs");
3
+ const require_native_deep_link = require("./deep-link.cjs");
3
4
  const require_native_fingerprint = require("./fingerprint.cjs");
4
5
  const require_native_setup = require("./setup.cjs");
6
+ exports.deepLink = require_native_deep_link.deepLink;
5
7
  exports.getDeterministicFingerprint = require_native_fingerprint.getDeterministicFingerprint;
6
8
  exports.getDeviceId = require_native_setup.getDeviceId;
7
9
  exports.getDeviceType = require_native_setup.getDeviceType;
@@ -1,4 +1,5 @@
1
1
  import { useAppAnalytics } from "../hooks/use-app-analytics.cjs";
2
+ import { deepLink } from "./deep-link.cjs";
2
3
  import { DeterministicFingerprint, ProbabilisticFingerprint, getDeterministicFingerprint, getProbabilisticFingerprint } from "./fingerprint.cjs";
3
4
  import { getDeviceId, getDeviceType, getTags, storage } from "./setup.cjs";
4
- export { type DeterministicFingerprint, type ProbabilisticFingerprint, getDeterministicFingerprint, getDeviceId, getDeviceType, getProbabilisticFingerprint, getTags, storage, useAppAnalytics };
5
+ export { type DeterministicFingerprint, type ProbabilisticFingerprint, deepLink, getDeterministicFingerprint, getDeviceId, getDeviceType, getProbabilisticFingerprint, getTags, storage, useAppAnalytics };
@@ -1,4 +1,5 @@
1
1
  import { useAppAnalytics } from "../hooks/use-app-analytics.mjs";
2
+ import { deepLink } from "./deep-link.mjs";
2
3
  import { DeterministicFingerprint, ProbabilisticFingerprint, getDeterministicFingerprint, getProbabilisticFingerprint } from "./fingerprint.mjs";
3
4
  import { getDeviceId, getDeviceType, getTags, storage } from "./setup.mjs";
4
- export { type DeterministicFingerprint, type ProbabilisticFingerprint, getDeterministicFingerprint, getDeviceId, getDeviceType, getProbabilisticFingerprint, getTags, storage, useAppAnalytics };
5
+ export { type DeterministicFingerprint, type ProbabilisticFingerprint, deepLink, getDeterministicFingerprint, getDeviceId, getDeviceType, getProbabilisticFingerprint, getTags, storage, useAppAnalytics };
@@ -1,4 +1,5 @@
1
1
  import { useAppAnalytics } from "../hooks/use-app-analytics.mjs";
2
+ import { deepLink } from "./deep-link.mjs";
2
3
  import { getDeterministicFingerprint, getProbabilisticFingerprint } from "./fingerprint.mjs";
3
4
  import { getDeviceId, getDeviceType, getTags, storage } from "./setup.mjs";
4
- export { getDeterministicFingerprint, getDeviceId, getDeviceType, getProbabilisticFingerprint, getTags, storage, useAppAnalytics };
5
+ export { deepLink, getDeterministicFingerprint, getDeviceId, getDeviceType, getProbabilisticFingerprint, getTags, storage, useAppAnalytics };
@@ -2,13 +2,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_setup_index = require("../setup/index.cjs");
3
3
  const require_constants_storage = require("../constants/storage.cjs");
4
4
  let react_native = require("react-native");
5
+ let react_native_url_polyfill = require("react-native-url-polyfill");
5
6
  let expo_application = require("expo-application");
6
7
  let expo_device = require("expo-device");
7
8
  let expo_localization = require("expo-localization");
8
9
  require("expo-sqlite/localStorage/install");
9
10
  let expo_crypto = require("expo-crypto");
10
11
  let expo_tracking_transparency = require("expo-tracking-transparency");
11
- let react_native_url_polyfill = require("react-native-url-polyfill");
12
12
  //#region src/native/setup.ts
13
13
  const map = /* @__PURE__ */ new Map();
14
14
  const storage = {
@@ -105,6 +105,7 @@ async function getTags() {
105
105
  const install_referrer = await getInstallReferrer();
106
106
  if (install_referrer && installLaunch === void 0) installLaunch = claimInstallReferrer();
107
107
  const params = new react_native_url_polyfill.URLSearchParams(installLaunch ? install_referrer : void 0);
108
+ const opening = await require_setup_index.config.deepLink?.getTags();
108
109
  const tags = {
109
110
  os: `${expo_device.osName} ${expo_device.osVersion}`,
110
111
  os_name: expo_device.osName ?? void 0,
@@ -131,7 +132,8 @@ async function getTags() {
131
132
  utm_id: params.get("utm_id") ?? void 0,
132
133
  utm_source_platform: params.get("utm_source_platform") ?? void 0,
133
134
  utm_creative_format: params.get("utm_creative_format") ?? void 0,
134
- utm_marketing_tactic: params.get("utm_marketing_tactic") ?? void 0
135
+ utm_marketing_tactic: params.get("utm_marketing_tactic") ?? void 0,
136
+ ...opening
135
137
  };
136
138
  require_setup_index.cache.tags = tags;
137
139
  return tags;
@@ -1 +1 @@
1
- {"version":3,"file":"setup.cjs","names":["Platform","getInstallReferrerAsync","getIosIdForVendorAsync","getAndroidId","randomUUID","deviceType","DeviceType","config","keys","Dimensions","URLSearchParams","osName","osVersion","modelName","manufacturer","modelId","PixelRatio","getLocales","getCalendars","getAdvertisingId"],"sources":["../../src/native/setup.ts"],"sourcesContent":["import 'expo-sqlite/localStorage/install';\nimport { getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync } from 'expo-application';\nimport { randomUUID } from 'expo-crypto';\nimport {\n DeviceType,\n deviceType,\n manufacturer,\n modelId,\n modelName,\n osName,\n osVersion,\n} from 'expo-device';\nimport { getCalendars, getLocales } from 'expo-localization';\nimport { getAdvertisingId } from 'expo-tracking-transparency';\nimport { Dimensions, PixelRatio, Platform } from 'react-native';\nimport { URLSearchParams } from 'react-native-url-polyfill';\nimport { keys } from '../constants/storage';\nimport { type Storage, cache, config } from '../setup/index';\nimport type { TrackTags } from '../track/types';\n\nconst map = new Map<string, string>();\n\nexport const storage: Storage = {\n getItem: (key) => {\n try {\n return localStorage.getItem(key);\n } catch {\n console.error('localStorage is not available');\n return map.get(key) ?? null;\n }\n },\n setItem: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch {\n console.error('localStorage is not available');\n map.set(key, value);\n }\n },\n};\n\n/**\n * `getTags` runs once per event now, and both of these reach for a native module. Neither answer\n * can change while the app is running, so each is resolved once and the promise is reused. A\n * failed lookup is not cached, so the next event tries again.\n */\nlet deviceIdPromise: Promise<string> | undefined;\nlet installReferrerPromise: Promise<string | undefined> | undefined;\n\nexport function getDeviceId(): Promise<string> {\n deviceIdPromise ??= resolveDeviceId().catch((error: unknown) => {\n deviceIdPromise = undefined;\n throw error;\n });\n return deviceIdPromise;\n}\n\nfunction getInstallReferrer(): Promise<string | undefined> {\n if (Platform.OS !== 'android') return Promise.resolve(undefined);\n installReferrerPromise ??= getInstallReferrerAsync().catch((error: unknown) => {\n installReferrerPromise = undefined;\n throw error;\n });\n return installReferrerPromise;\n}\n\nasync function resolveDeviceId(): Promise<string> {\n let deviceId: string | null = null;\n if (Platform.OS === 'ios') {\n deviceId = await getIosIdForVendorAsync();\n } else if (Platform.OS === 'android') {\n deviceId = getAndroidId();\n }\n if (!deviceId) {\n deviceId = localStorage.getItem('device_id');\n if (!deviceId) {\n deviceId = randomUUID();\n localStorage.setItem('device_id', deviceId);\n }\n }\n return deviceId;\n}\n\nexport function getDeviceType(): string | undefined {\n switch (deviceType) {\n case DeviceType.PHONE:\n return 'mobile';\n case DeviceType.TABLET:\n return 'tablet';\n case DeviceType.DESKTOP:\n return 'desktop';\n case DeviceType.TV:\n return 'smarttv';\n default:\n return undefined;\n }\n}\n\n/**\n * The install referrer's utm belongs to one launch: the first one that has the referrer in hand\n * — normally the install launch, since `first_open` is the first event the app tracks and\n * tracking it builds the first tags. That launch claims the referrer by writing a marker of its\n * own, and holds the claim for the rest of the process, so every event of the launch and the\n * visitor created from it carry the utm; every later launch finds the marker and sends the raw\n * `install_referrer` alone. Cleared storage and a reinstall lose the marker and claim again,\n * exactly as they make `first_open` fire again.\n *\n * Claimed only once a referrer has actually been resolved. The Install Referrer API needs the\n * Play Store service, which is at its least available right after an install; a launch that\n * could not reach it must not spend the claim on nothing, because the referrer stays readable\n * for 90 days and a later launch can still take it — late attribution, rather than none. iOS\n * has no referrer and so never claims.\n *\n * A marker of its own rather than `first_open_time`, so that nothing here depends on when the\n * hook writes that one relative to the first `getTags`. The storage read waits for that call:\n * `setupAnalytics` and this module's evaluation can run where no storage exists.\n */\nlet installLaunch: boolean | undefined;\n\nfunction claimInstallReferrer(): boolean {\n if (config.storage.getItem(keys.install_referrer_claim_time)) return false;\n config.storage.setItem(keys.install_referrer_claim_time, new Date().toISOString());\n return true;\n}\n\nexport async function getTags(): Promise<TrackTags> {\n const screen = Dimensions.get('screen');\n const screen_width = Math.floor(screen.width);\n const screen_height = Math.floor(screen.height);\n\n // The install referrer never changes, and it used to be spread into `utm_*` on every launch —\n // so every session of an Android install reported the install campaign as its own acquisition\n // for as long as the app stayed installed, and a report reading a session's tags could not tell\n // the install from the thousandth open. The campaign is the install's touch, not every\n // session's.\n const install_referrer = await getInstallReferrer();\n if (install_referrer && installLaunch === undefined) installLaunch = claimInstallReferrer();\n const params = new URLSearchParams(installLaunch ? install_referrer : undefined);\n\n const tags: TrackTags = {\n os: `${osName} ${osVersion}`,\n os_name: osName ?? undefined,\n os_version: osVersion ?? undefined,\n device: modelName ?? undefined,\n device_id: await getDeviceId(),\n device_type: getDeviceType(),\n device_vendor: manufacturer ?? undefined,\n device_model_id: modelId ?? undefined,\n device_pixel_ratio: PixelRatio.get(),\n screen_width,\n screen_height,\n screen_resolution: `${screen_width}x${screen_height}`,\n release: config.release,\n language: getLocales().at(0)?.languageTag ?? 'en',\n time_zone: getCalendars().at(0)?.timeZone ?? 'UTC',\n // ads\n advertising_id: getAdvertisingId() ?? undefined,\n install_referrer,\n // utm params: from the install referrer, on the launch that claimed it\n utm_source: params.get('utm_source') ?? undefined,\n utm_medium: params.get('utm_medium') ?? undefined,\n utm_campaign: params.get('utm_campaign') ?? undefined,\n utm_term: params.get('utm_term') ?? undefined,\n utm_content: params.get('utm_content') ?? undefined,\n utm_id: params.get('utm_id') ?? undefined,\n utm_source_platform: params.get('utm_source_platform') ?? undefined,\n utm_creative_format: params.get('utm_creative_format') ?? undefined,\n utm_marketing_tactic: params.get('utm_marketing_tactic') ?? undefined,\n };\n\n cache.tags = tags;\n return tags;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"setup.cjs","names":["Platform","getInstallReferrerAsync","getIosIdForVendorAsync","getAndroidId","randomUUID","deviceType","DeviceType","config","keys","Dimensions","URLSearchParams","osName","osVersion","modelName","manufacturer","modelId","PixelRatio","getLocales","getCalendars","getAdvertisingId"],"sources":["../../src/native/setup.ts"],"sourcesContent":["import 'expo-sqlite/localStorage/install';\nimport { getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync } from 'expo-application';\nimport { randomUUID } from 'expo-crypto';\nimport {\n DeviceType,\n deviceType,\n manufacturer,\n modelId,\n modelName,\n osName,\n osVersion,\n} from 'expo-device';\nimport { getCalendars, getLocales } from 'expo-localization';\nimport { getAdvertisingId } from 'expo-tracking-transparency';\nimport { Dimensions, PixelRatio, Platform } from 'react-native';\nimport { URLSearchParams } from 'react-native-url-polyfill';\nimport { keys } from '../constants/storage';\nimport { type Storage, cache, config } from '../setup/index';\nimport type { TrackTags } from '../track/types';\n\nconst map = new Map<string, string>();\n\nexport const storage: Storage = {\n getItem: (key) => {\n try {\n return localStorage.getItem(key);\n } catch {\n console.error('localStorage is not available');\n return map.get(key) ?? null;\n }\n },\n setItem: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch {\n console.error('localStorage is not available');\n map.set(key, value);\n }\n },\n};\n\n/**\n * `getTags` runs once per event now, and both of these reach for a native module. Neither answer\n * can change while the app is running, so each is resolved once and the promise is reused. A\n * failed lookup is not cached, so the next event tries again.\n */\nlet deviceIdPromise: Promise<string> | undefined;\nlet installReferrerPromise: Promise<string | undefined> | undefined;\n\nexport function getDeviceId(): Promise<string> {\n deviceIdPromise ??= resolveDeviceId().catch((error: unknown) => {\n deviceIdPromise = undefined;\n throw error;\n });\n return deviceIdPromise;\n}\n\nfunction getInstallReferrer(): Promise<string | undefined> {\n if (Platform.OS !== 'android') return Promise.resolve(undefined);\n installReferrerPromise ??= getInstallReferrerAsync().catch((error: unknown) => {\n installReferrerPromise = undefined;\n throw error;\n });\n return installReferrerPromise;\n}\n\nasync function resolveDeviceId(): Promise<string> {\n let deviceId: string | null = null;\n if (Platform.OS === 'ios') {\n deviceId = await getIosIdForVendorAsync();\n } else if (Platform.OS === 'android') {\n deviceId = getAndroidId();\n }\n if (!deviceId) {\n deviceId = localStorage.getItem('device_id');\n if (!deviceId) {\n deviceId = randomUUID();\n localStorage.setItem('device_id', deviceId);\n }\n }\n return deviceId;\n}\n\nexport function getDeviceType(): string | undefined {\n switch (deviceType) {\n case DeviceType.PHONE:\n return 'mobile';\n case DeviceType.TABLET:\n return 'tablet';\n case DeviceType.DESKTOP:\n return 'desktop';\n case DeviceType.TV:\n return 'smarttv';\n default:\n return undefined;\n }\n}\n\n/**\n * The install referrer's utm belongs to one launch: the first one that has the referrer in hand\n * — normally the install launch, since `first_open` is the first event the app tracks and\n * tracking it builds the first tags. That launch claims the referrer by writing a marker of its\n * own, and holds the claim for the rest of the process, so every event of the launch and the\n * visitor created from it carry the utm; every later launch finds the marker and sends the raw\n * `install_referrer` alone. Cleared storage and a reinstall lose the marker and claim again,\n * exactly as they make `first_open` fire again.\n *\n * Claimed only once a referrer has actually been resolved. The Install Referrer API needs the\n * Play Store service, which is at its least available right after an install; a launch that\n * could not reach it must not spend the claim on nothing, because the referrer stays readable\n * for 90 days and a later launch can still take it — late attribution, rather than none. iOS\n * has no referrer and so never claims.\n *\n * A marker of its own rather than `first_open_time`, so that nothing here depends on when the\n * hook writes that one relative to the first `getTags`. The storage read waits for that call:\n * `setupAnalytics` and this module's evaluation can run where no storage exists.\n */\nlet installLaunch: boolean | undefined;\n\nfunction claimInstallReferrer(): boolean {\n if (config.storage.getItem(keys.install_referrer_claim_time)) return false;\n config.storage.setItem(keys.install_referrer_claim_time, new Date().toISOString());\n return true;\n}\n\nexport async function getTags(): Promise<TrackTags> {\n const screen = Dimensions.get('screen');\n const screen_width = Math.floor(screen.width);\n const screen_height = Math.floor(screen.height);\n\n // The install referrer never changes, and it used to be spread into `utm_*` on every launch —\n // so every session of an Android install reported the install campaign as its own acquisition\n // for as long as the app stayed installed, and a report reading a session's tags could not tell\n // the install from the thousandth open. The campaign is the install's touch, not every\n // session's.\n const install_referrer = await getInstallReferrer();\n if (install_referrer && installLaunch === undefined) installLaunch = claimInstallReferrer();\n const params = new URLSearchParams(installLaunch ? install_referrer : undefined);\n const opening = await config.deepLink?.getTags();\n\n const tags: TrackTags = {\n os: `${osName} ${osVersion}`,\n os_name: osName ?? undefined,\n os_version: osVersion ?? undefined,\n device: modelName ?? undefined,\n device_id: await getDeviceId(),\n device_type: getDeviceType(),\n device_vendor: manufacturer ?? undefined,\n device_model_id: modelId ?? undefined,\n device_pixel_ratio: PixelRatio.get(),\n screen_width,\n screen_height,\n screen_resolution: `${screen_width}x${screen_height}`,\n release: config.release,\n language: getLocales().at(0)?.languageTag ?? 'en',\n time_zone: getCalendars().at(0)?.timeZone ?? 'UTC',\n // ads\n advertising_id: getAdvertisingId() ?? undefined,\n install_referrer,\n // utm params: from the install referrer, on the launch that claimed it\n utm_source: params.get('utm_source') ?? undefined,\n utm_medium: params.get('utm_medium') ?? undefined,\n utm_campaign: params.get('utm_campaign') ?? undefined,\n utm_term: params.get('utm_term') ?? undefined,\n utm_content: params.get('utm_content') ?? undefined,\n utm_id: params.get('utm_id') ?? undefined,\n utm_source_platform: params.get('utm_source_platform') ?? undefined,\n utm_creative_format: params.get('utm_creative_format') ?? undefined,\n utm_marketing_tactic: params.get('utm_marketing_tactic') ?? undefined,\n // the link that opened the app (`setupAnalytics({ deepLink })`): its URL, utm and click ids,\n // over the install referrer's\n ...opening,\n };\n\n cache.tags = tags;\n return tags;\n}\n"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import { cache, config } from "../setup/index.mjs";
2
2
  import { keys } from "../constants/storage.mjs";
3
3
  import { Dimensions, PixelRatio, Platform } from "react-native";
4
+ import { URLSearchParams } from "react-native-url-polyfill";
4
5
  import { getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync } from "expo-application";
5
6
  import { DeviceType, deviceType, manufacturer, modelId, modelName, osName, osVersion } from "expo-device";
6
7
  import { getCalendars, getLocales } from "expo-localization";
7
8
  import "expo-sqlite/localStorage/install";
8
9
  import { randomUUID } from "expo-crypto";
9
10
  import { getAdvertisingId } from "expo-tracking-transparency";
10
- import { URLSearchParams } from "react-native-url-polyfill";
11
11
  //#region src/native/setup.ts
12
12
  const map = /* @__PURE__ */ new Map();
13
13
  const storage = {
@@ -104,6 +104,7 @@ async function getTags() {
104
104
  const install_referrer = await getInstallReferrer();
105
105
  if (install_referrer && installLaunch === void 0) installLaunch = claimInstallReferrer();
106
106
  const params = new URLSearchParams(installLaunch ? install_referrer : void 0);
107
+ const opening = await config.deepLink?.getTags();
107
108
  const tags = {
108
109
  os: `${osName} ${osVersion}`,
109
110
  os_name: osName ?? void 0,
@@ -130,7 +131,8 @@ async function getTags() {
130
131
  utm_id: params.get("utm_id") ?? void 0,
131
132
  utm_source_platform: params.get("utm_source_platform") ?? void 0,
132
133
  utm_creative_format: params.get("utm_creative_format") ?? void 0,
133
- utm_marketing_tactic: params.get("utm_marketing_tactic") ?? void 0
134
+ utm_marketing_tactic: params.get("utm_marketing_tactic") ?? void 0,
135
+ ...opening
134
136
  };
135
137
  cache.tags = tags;
136
138
  return tags;
@@ -1 +1 @@
1
- {"version":3,"file":"setup.mjs","names":[],"sources":["../../src/native/setup.ts"],"sourcesContent":["import 'expo-sqlite/localStorage/install';\nimport { getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync } from 'expo-application';\nimport { randomUUID } from 'expo-crypto';\nimport {\n DeviceType,\n deviceType,\n manufacturer,\n modelId,\n modelName,\n osName,\n osVersion,\n} from 'expo-device';\nimport { getCalendars, getLocales } from 'expo-localization';\nimport { getAdvertisingId } from 'expo-tracking-transparency';\nimport { Dimensions, PixelRatio, Platform } from 'react-native';\nimport { URLSearchParams } from 'react-native-url-polyfill';\nimport { keys } from '../constants/storage';\nimport { type Storage, cache, config } from '../setup/index';\nimport type { TrackTags } from '../track/types';\n\nconst map = new Map<string, string>();\n\nexport const storage: Storage = {\n getItem: (key) => {\n try {\n return localStorage.getItem(key);\n } catch {\n console.error('localStorage is not available');\n return map.get(key) ?? null;\n }\n },\n setItem: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch {\n console.error('localStorage is not available');\n map.set(key, value);\n }\n },\n};\n\n/**\n * `getTags` runs once per event now, and both of these reach for a native module. Neither answer\n * can change while the app is running, so each is resolved once and the promise is reused. A\n * failed lookup is not cached, so the next event tries again.\n */\nlet deviceIdPromise: Promise<string> | undefined;\nlet installReferrerPromise: Promise<string | undefined> | undefined;\n\nexport function getDeviceId(): Promise<string> {\n deviceIdPromise ??= resolveDeviceId().catch((error: unknown) => {\n deviceIdPromise = undefined;\n throw error;\n });\n return deviceIdPromise;\n}\n\nfunction getInstallReferrer(): Promise<string | undefined> {\n if (Platform.OS !== 'android') return Promise.resolve(undefined);\n installReferrerPromise ??= getInstallReferrerAsync().catch((error: unknown) => {\n installReferrerPromise = undefined;\n throw error;\n });\n return installReferrerPromise;\n}\n\nasync function resolveDeviceId(): Promise<string> {\n let deviceId: string | null = null;\n if (Platform.OS === 'ios') {\n deviceId = await getIosIdForVendorAsync();\n } else if (Platform.OS === 'android') {\n deviceId = getAndroidId();\n }\n if (!deviceId) {\n deviceId = localStorage.getItem('device_id');\n if (!deviceId) {\n deviceId = randomUUID();\n localStorage.setItem('device_id', deviceId);\n }\n }\n return deviceId;\n}\n\nexport function getDeviceType(): string | undefined {\n switch (deviceType) {\n case DeviceType.PHONE:\n return 'mobile';\n case DeviceType.TABLET:\n return 'tablet';\n case DeviceType.DESKTOP:\n return 'desktop';\n case DeviceType.TV:\n return 'smarttv';\n default:\n return undefined;\n }\n}\n\n/**\n * The install referrer's utm belongs to one launch: the first one that has the referrer in hand\n * — normally the install launch, since `first_open` is the first event the app tracks and\n * tracking it builds the first tags. That launch claims the referrer by writing a marker of its\n * own, and holds the claim for the rest of the process, so every event of the launch and the\n * visitor created from it carry the utm; every later launch finds the marker and sends the raw\n * `install_referrer` alone. Cleared storage and a reinstall lose the marker and claim again,\n * exactly as they make `first_open` fire again.\n *\n * Claimed only once a referrer has actually been resolved. The Install Referrer API needs the\n * Play Store service, which is at its least available right after an install; a launch that\n * could not reach it must not spend the claim on nothing, because the referrer stays readable\n * for 90 days and a later launch can still take it — late attribution, rather than none. iOS\n * has no referrer and so never claims.\n *\n * A marker of its own rather than `first_open_time`, so that nothing here depends on when the\n * hook writes that one relative to the first `getTags`. The storage read waits for that call:\n * `setupAnalytics` and this module's evaluation can run where no storage exists.\n */\nlet installLaunch: boolean | undefined;\n\nfunction claimInstallReferrer(): boolean {\n if (config.storage.getItem(keys.install_referrer_claim_time)) return false;\n config.storage.setItem(keys.install_referrer_claim_time, new Date().toISOString());\n return true;\n}\n\nexport async function getTags(): Promise<TrackTags> {\n const screen = Dimensions.get('screen');\n const screen_width = Math.floor(screen.width);\n const screen_height = Math.floor(screen.height);\n\n // The install referrer never changes, and it used to be spread into `utm_*` on every launch —\n // so every session of an Android install reported the install campaign as its own acquisition\n // for as long as the app stayed installed, and a report reading a session's tags could not tell\n // the install from the thousandth open. The campaign is the install's touch, not every\n // session's.\n const install_referrer = await getInstallReferrer();\n if (install_referrer && installLaunch === undefined) installLaunch = claimInstallReferrer();\n const params = new URLSearchParams(installLaunch ? install_referrer : undefined);\n\n const tags: TrackTags = {\n os: `${osName} ${osVersion}`,\n os_name: osName ?? undefined,\n os_version: osVersion ?? undefined,\n device: modelName ?? undefined,\n device_id: await getDeviceId(),\n device_type: getDeviceType(),\n device_vendor: manufacturer ?? undefined,\n device_model_id: modelId ?? undefined,\n device_pixel_ratio: PixelRatio.get(),\n screen_width,\n screen_height,\n screen_resolution: `${screen_width}x${screen_height}`,\n release: config.release,\n language: getLocales().at(0)?.languageTag ?? 'en',\n time_zone: getCalendars().at(0)?.timeZone ?? 'UTC',\n // ads\n advertising_id: getAdvertisingId() ?? undefined,\n install_referrer,\n // utm params: from the install referrer, on the launch that claimed it\n utm_source: params.get('utm_source') ?? undefined,\n utm_medium: params.get('utm_medium') ?? undefined,\n utm_campaign: params.get('utm_campaign') ?? undefined,\n utm_term: params.get('utm_term') ?? undefined,\n utm_content: params.get('utm_content') ?? undefined,\n utm_id: params.get('utm_id') ?? undefined,\n utm_source_platform: params.get('utm_source_platform') ?? undefined,\n utm_creative_format: params.get('utm_creative_format') ?? undefined,\n utm_marketing_tactic: params.get('utm_marketing_tactic') ?? undefined,\n };\n\n cache.tags = tags;\n return tags;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"setup.mjs","names":[],"sources":["../../src/native/setup.ts"],"sourcesContent":["import 'expo-sqlite/localStorage/install';\nimport { getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync } from 'expo-application';\nimport { randomUUID } from 'expo-crypto';\nimport {\n DeviceType,\n deviceType,\n manufacturer,\n modelId,\n modelName,\n osName,\n osVersion,\n} from 'expo-device';\nimport { getCalendars, getLocales } from 'expo-localization';\nimport { getAdvertisingId } from 'expo-tracking-transparency';\nimport { Dimensions, PixelRatio, Platform } from 'react-native';\nimport { URLSearchParams } from 'react-native-url-polyfill';\nimport { keys } from '../constants/storage';\nimport { type Storage, cache, config } from '../setup/index';\nimport type { TrackTags } from '../track/types';\n\nconst map = new Map<string, string>();\n\nexport const storage: Storage = {\n getItem: (key) => {\n try {\n return localStorage.getItem(key);\n } catch {\n console.error('localStorage is not available');\n return map.get(key) ?? null;\n }\n },\n setItem: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch {\n console.error('localStorage is not available');\n map.set(key, value);\n }\n },\n};\n\n/**\n * `getTags` runs once per event now, and both of these reach for a native module. Neither answer\n * can change while the app is running, so each is resolved once and the promise is reused. A\n * failed lookup is not cached, so the next event tries again.\n */\nlet deviceIdPromise: Promise<string> | undefined;\nlet installReferrerPromise: Promise<string | undefined> | undefined;\n\nexport function getDeviceId(): Promise<string> {\n deviceIdPromise ??= resolveDeviceId().catch((error: unknown) => {\n deviceIdPromise = undefined;\n throw error;\n });\n return deviceIdPromise;\n}\n\nfunction getInstallReferrer(): Promise<string | undefined> {\n if (Platform.OS !== 'android') return Promise.resolve(undefined);\n installReferrerPromise ??= getInstallReferrerAsync().catch((error: unknown) => {\n installReferrerPromise = undefined;\n throw error;\n });\n return installReferrerPromise;\n}\n\nasync function resolveDeviceId(): Promise<string> {\n let deviceId: string | null = null;\n if (Platform.OS === 'ios') {\n deviceId = await getIosIdForVendorAsync();\n } else if (Platform.OS === 'android') {\n deviceId = getAndroidId();\n }\n if (!deviceId) {\n deviceId = localStorage.getItem('device_id');\n if (!deviceId) {\n deviceId = randomUUID();\n localStorage.setItem('device_id', deviceId);\n }\n }\n return deviceId;\n}\n\nexport function getDeviceType(): string | undefined {\n switch (deviceType) {\n case DeviceType.PHONE:\n return 'mobile';\n case DeviceType.TABLET:\n return 'tablet';\n case DeviceType.DESKTOP:\n return 'desktop';\n case DeviceType.TV:\n return 'smarttv';\n default:\n return undefined;\n }\n}\n\n/**\n * The install referrer's utm belongs to one launch: the first one that has the referrer in hand\n * — normally the install launch, since `first_open` is the first event the app tracks and\n * tracking it builds the first tags. That launch claims the referrer by writing a marker of its\n * own, and holds the claim for the rest of the process, so every event of the launch and the\n * visitor created from it carry the utm; every later launch finds the marker and sends the raw\n * `install_referrer` alone. Cleared storage and a reinstall lose the marker and claim again,\n * exactly as they make `first_open` fire again.\n *\n * Claimed only once a referrer has actually been resolved. The Install Referrer API needs the\n * Play Store service, which is at its least available right after an install; a launch that\n * could not reach it must not spend the claim on nothing, because the referrer stays readable\n * for 90 days and a later launch can still take it — late attribution, rather than none. iOS\n * has no referrer and so never claims.\n *\n * A marker of its own rather than `first_open_time`, so that nothing here depends on when the\n * hook writes that one relative to the first `getTags`. The storage read waits for that call:\n * `setupAnalytics` and this module's evaluation can run where no storage exists.\n */\nlet installLaunch: boolean | undefined;\n\nfunction claimInstallReferrer(): boolean {\n if (config.storage.getItem(keys.install_referrer_claim_time)) return false;\n config.storage.setItem(keys.install_referrer_claim_time, new Date().toISOString());\n return true;\n}\n\nexport async function getTags(): Promise<TrackTags> {\n const screen = Dimensions.get('screen');\n const screen_width = Math.floor(screen.width);\n const screen_height = Math.floor(screen.height);\n\n // The install referrer never changes, and it used to be spread into `utm_*` on every launch —\n // so every session of an Android install reported the install campaign as its own acquisition\n // for as long as the app stayed installed, and a report reading a session's tags could not tell\n // the install from the thousandth open. The campaign is the install's touch, not every\n // session's.\n const install_referrer = await getInstallReferrer();\n if (install_referrer && installLaunch === undefined) installLaunch = claimInstallReferrer();\n const params = new URLSearchParams(installLaunch ? install_referrer : undefined);\n const opening = await config.deepLink?.getTags();\n\n const tags: TrackTags = {\n os: `${osName} ${osVersion}`,\n os_name: osName ?? undefined,\n os_version: osVersion ?? undefined,\n device: modelName ?? undefined,\n device_id: await getDeviceId(),\n device_type: getDeviceType(),\n device_vendor: manufacturer ?? undefined,\n device_model_id: modelId ?? undefined,\n device_pixel_ratio: PixelRatio.get(),\n screen_width,\n screen_height,\n screen_resolution: `${screen_width}x${screen_height}`,\n release: config.release,\n language: getLocales().at(0)?.languageTag ?? 'en',\n time_zone: getCalendars().at(0)?.timeZone ?? 'UTC',\n // ads\n advertising_id: getAdvertisingId() ?? undefined,\n install_referrer,\n // utm params: from the install referrer, on the launch that claimed it\n utm_source: params.get('utm_source') ?? undefined,\n utm_medium: params.get('utm_medium') ?? undefined,\n utm_campaign: params.get('utm_campaign') ?? undefined,\n utm_term: params.get('utm_term') ?? undefined,\n utm_content: params.get('utm_content') ?? undefined,\n utm_id: params.get('utm_id') ?? undefined,\n utm_source_platform: params.get('utm_source_platform') ?? undefined,\n utm_creative_format: params.get('utm_creative_format') ?? undefined,\n utm_marketing_tactic: params.get('utm_marketing_tactic') ?? undefined,\n // the link that opened the app (`setupAnalytics({ deepLink })`): its URL, utm and click ids,\n // over the install referrer's\n ...opening,\n };\n\n cache.tags = tags;\n return tags;\n}\n"],"mappings":"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"}
@@ -11,7 +11,8 @@ const config = {
11
11
  getDeviceId: null,
12
12
  getHeaders: null,
13
13
  thirdPartyTrackers: [],
14
- thirdPartyUserSetters: []
14
+ thirdPartyUserSetters: [],
15
+ deepLink: void 0
15
16
  };
16
17
  function setupAnalytics(init) {
17
18
  config.release = init.release;
@@ -27,6 +28,12 @@ function setupAnalytics(init) {
27
28
  });
28
29
  config.thirdPartyTrackers = init.thirdPartyTrackers ?? [];
29
30
  config.thirdPartyUserSetters = init.thirdPartyUserSetters ?? [];
31
+ config.deepLink = init.deepLink;
32
+ try {
33
+ init.deepLink?.listen();
34
+ } catch (error) {
35
+ console.error("analytics deepLink.listen failed", error);
36
+ }
30
37
  }
31
38
  //#endregion
32
39
  exports.cache = cache;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/setup/index.ts"],"sourcesContent":["import type { Environment, Platform, ThirdPartyTracker, TrackTags } from '../track/types';\nimport type { ThirdPartyUserSetter } from '../visitor/types';\n\nexport interface Storage {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n}\n\nexport interface Options {\n release: string;\n storage: Storage;\n endpoint: string;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers?: ThirdPartyTracker[];\n thirdPartyUserSetters?: ThirdPartyUserSetter[];\n}\n\ninterface Config {\n release: string;\n endpoint: string;\n storage: Storage;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers: ThirdPartyTracker[];\n thirdPartyUserSetters: ThirdPartyUserSetter[];\n}\n\ninterface Cache {\n tags: TrackTags | null;\n}\n\nexport const cache: Cache = {\n tags: null,\n};\n\n// oxlint-disable typescript/no-non-null-assertion\nexport const config: Config = {\n endpoint: '',\n release: '0.0.0',\n storage: null!,\n platform: null!,\n environment: null!,\n getTags: null!,\n getDeviceId: null!,\n getHeaders: null!,\n thirdPartyTrackers: [],\n thirdPartyUserSetters: [],\n};\n// oxlint-enable typescript/no-non-null-assertion\n\nexport function setupAnalytics(init: Options) {\n config.release = init.release;\n config.storage = init.storage;\n config.platform = init.platform;\n config.environment = init.environment;\n config.endpoint = init.endpoint.endsWith('/') ? init.endpoint.slice(0, -1) : init.endpoint;\n config.getTags = init.getTags;\n config.getDeviceId = init.getDeviceId;\n config.getHeaders = async () => ({\n 'Content-Type': 'application/json',\n ...(await init.getHeaders?.()),\n });\n config.thirdPartyTrackers = init.thirdPartyTrackers ?? [];\n config.thirdPartyUserSetters = init.thirdPartyUserSetters ?? [];\n}\n"],"mappings":";;AAsCA,MAAa,QAAe,EAC1B,MAAM,KACR;AAGA,MAAa,SAAiB;CAC5B,UAAU;CACV,SAAS;CACT,SAAS;CACT,UAAU;CACV,aAAa;CACb,SAAS;CACT,aAAa;CACb,YAAY;CACZ,oBAAoB,CAAC;CACrB,uBAAuB,CAAC;AAC1B;AAGA,SAAgB,eAAe,MAAe;CAC5C,OAAO,UAAU,KAAK;CACtB,OAAO,UAAU,KAAK;CACtB,OAAO,WAAW,KAAK;CACvB,OAAO,cAAc,KAAK;CAC1B,OAAO,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;CAClF,OAAO,UAAU,KAAK;CACtB,OAAO,cAAc,KAAK;CAC1B,OAAO,aAAa,aAAa;EAC/B,gBAAgB;EAChB,GAAI,MAAM,KAAK,aAAa;CAC9B;CACA,OAAO,qBAAqB,KAAK,sBAAsB,CAAC;CACxD,OAAO,wBAAwB,KAAK,yBAAyB,CAAC;AAChE"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/setup/index.ts"],"sourcesContent":["import type { Environment, Platform, ThirdPartyTracker, TrackTags } from '../track/types';\nimport type { ThirdPartyUserSetter } from '../visitor/types';\n\nexport interface Storage {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n}\n\n/**\n * The link that opened the current visit of an app — a universal link, an app link, a custom\n * scheme — whose URL, utm and click ids land the visit as a web page's URL does.\n * `@shware/analytics/native` provides one (`deepLink`).\n */\nexport interface DeepLink {\n /** Starts following the links that open the app; `setupAnalytics` calls it once. */\n listen: () => void;\n /** The opening link's tags (`page_location`, utm, click ids); empty without one. */\n getTags: () => TrackTags | Promise<TrackTags>;\n}\n\nexport interface Options {\n release: string;\n storage: Storage;\n endpoint: string;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers?: ThirdPartyTracker[];\n thirdPartyUserSetters?: ThirdPartyUserSetter[];\n /** An app's opening link, which native's `getTags` merges into every event's tags. */\n deepLink?: DeepLink;\n}\n\ninterface Config {\n release: string;\n endpoint: string;\n storage: Storage;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers: ThirdPartyTracker[];\n thirdPartyUserSetters: ThirdPartyUserSetter[];\n deepLink: DeepLink | undefined;\n}\n\ninterface Cache {\n tags: TrackTags | null;\n}\n\nexport const cache: Cache = {\n tags: null,\n};\n\n// oxlint-disable typescript/no-non-null-assertion\nexport const config: Config = {\n endpoint: '',\n release: '0.0.0',\n storage: null!,\n platform: null!,\n environment: null!,\n getTags: null!,\n getDeviceId: null!,\n getHeaders: null!,\n thirdPartyTrackers: [],\n thirdPartyUserSetters: [],\n deepLink: undefined,\n};\n// oxlint-enable typescript/no-non-null-assertion\n\nexport function setupAnalytics(init: Options) {\n config.release = init.release;\n config.storage = init.storage;\n config.platform = init.platform;\n config.environment = init.environment;\n config.endpoint = init.endpoint.endsWith('/') ? init.endpoint.slice(0, -1) : init.endpoint;\n config.getTags = init.getTags;\n config.getDeviceId = init.getDeviceId;\n config.getHeaders = async () => ({\n 'Content-Type': 'application/json',\n ...(await init.getHeaders?.()),\n });\n config.thirdPartyTrackers = init.thirdPartyTrackers ?? [];\n config.thirdPartyUserSetters = init.thirdPartyUserSetters ?? [];\n config.deepLink = init.deepLink;\n // Logged, not thrown: the links are worth less than the setup they would break.\n try {\n init.deepLink?.listen();\n } catch (error) {\n console.error('analytics deepLink.listen failed', error);\n }\n}\n"],"mappings":";;AAqDA,MAAa,QAAe,EAC1B,MAAM,KACR;AAGA,MAAa,SAAiB;CAC5B,UAAU;CACV,SAAS;CACT,SAAS;CACT,UAAU;CACV,aAAa;CACb,SAAS;CACT,aAAa;CACb,YAAY;CACZ,oBAAoB,CAAC;CACrB,uBAAuB,CAAC;CACxB,UAAU,KAAA;AACZ;AAGA,SAAgB,eAAe,MAAe;CAC5C,OAAO,UAAU,KAAK;CACtB,OAAO,UAAU,KAAK;CACtB,OAAO,WAAW,KAAK;CACvB,OAAO,cAAc,KAAK;CAC1B,OAAO,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;CAClF,OAAO,UAAU,KAAK;CACtB,OAAO,cAAc,KAAK;CAC1B,OAAO,aAAa,aAAa;EAC/B,gBAAgB;EAChB,GAAI,MAAM,KAAK,aAAa;CAC9B;CACA,OAAO,qBAAqB,KAAK,sBAAsB,CAAC;CACxD,OAAO,wBAAwB,KAAK,yBAAyB,CAAC;CAC9D,OAAO,WAAW,KAAK;CAEvB,IAAI;EACF,KAAK,UAAU,OAAO;CACxB,SAAS,OAAO;EACd,QAAQ,MAAM,oCAAoC,KAAK;CACzD;AACF"}
@@ -5,6 +5,17 @@ export interface Storage {
5
5
  getItem: (key: string) => string | null;
6
6
  setItem: (key: string, value: string) => void;
7
7
  }
8
+ /**
9
+ * The link that opened the current visit of an app — a universal link, an app link, a custom
10
+ * scheme — whose URL, utm and click ids land the visit as a web page's URL does.
11
+ * `@shware/analytics/native` provides one (`deepLink`).
12
+ */
13
+ export interface DeepLink {
14
+ /** Starts following the links that open the app; `setupAnalytics` calls it once. */
15
+ listen: () => void;
16
+ /** The opening link's tags (`page_location`, utm, click ids); empty without one. */
17
+ getTags: () => TrackTags | Promise<TrackTags>;
18
+ }
8
19
  export interface Options {
9
20
  release: string;
10
21
  storage: Storage;
@@ -16,6 +27,8 @@ export interface Options {
16
27
  getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
17
28
  thirdPartyTrackers?: ThirdPartyTracker[];
18
29
  thirdPartyUserSetters?: ThirdPartyUserSetter[];
30
+ /** An app's opening link, which native's `getTags` merges into every event's tags. */
31
+ deepLink?: DeepLink;
19
32
  }
20
33
  interface Config {
21
34
  release: string;
@@ -28,6 +41,7 @@ interface Config {
28
41
  getHeaders: () => Record<string, string> | Promise<Record<string, string>>;
29
42
  thirdPartyTrackers: ThirdPartyTracker[];
30
43
  thirdPartyUserSetters: ThirdPartyUserSetter[];
44
+ deepLink: DeepLink | undefined;
31
45
  }
32
46
  interface Cache {
33
47
  tags: TrackTags | null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/setup/index.ts"],"mappings":";;;iBAGiB;EACf,UAAU;EACV,UAAU,aAAa;;iBAGR;EACf;EACA,SAAS;EACT;EACA,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,mBAAmB,yBAAyB,QAAQ;EACpD,qBAAqB;EACrB,wBAAwB;;UAGhB;EACR;EACA;EACA,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,kBAAkB,yBAAyB,QAAQ;EACnD,oBAAoB;EACpB,uBAAuB;;UAGf;EACR,MAAM;;qBAGK,OAAO;qBAKP,QAAQ;wBAcL,eAAe,MAAM"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/setup/index.ts"],"mappings":";;;iBAGiB;EACf,UAAU;EACV,UAAU,aAAa;;;;;;;iBAQR;;EAEf;;EAEA,eAAe,YAAY,QAAQ;;iBAGpB;EACf;EACA,SAAS;EACT;EACA,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,mBAAmB,yBAAyB,QAAQ;EACpD,qBAAqB;EACrB,wBAAwB;;EAExB,WAAW;;UAGH;EACR;EACA;EACA,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,kBAAkB,yBAAyB,QAAQ;EACnD,oBAAoB;EACpB,uBAAuB;EACvB,UAAU;;UAGF;EACR,MAAM;;qBAGK,OAAO;qBAKP,QAAQ;wBAeL,eAAe,MAAM"}
@@ -5,6 +5,17 @@ export interface Storage {
5
5
  getItem: (key: string) => string | null;
6
6
  setItem: (key: string, value: string) => void;
7
7
  }
8
+ /**
9
+ * The link that opened the current visit of an app — a universal link, an app link, a custom
10
+ * scheme — whose URL, utm and click ids land the visit as a web page's URL does.
11
+ * `@shware/analytics/native` provides one (`deepLink`).
12
+ */
13
+ export interface DeepLink {
14
+ /** Starts following the links that open the app; `setupAnalytics` calls it once. */
15
+ listen: () => void;
16
+ /** The opening link's tags (`page_location`, utm, click ids); empty without one. */
17
+ getTags: () => TrackTags | Promise<TrackTags>;
18
+ }
8
19
  export interface Options {
9
20
  release: string;
10
21
  storage: Storage;
@@ -16,6 +27,8 @@ export interface Options {
16
27
  getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
17
28
  thirdPartyTrackers?: ThirdPartyTracker[];
18
29
  thirdPartyUserSetters?: ThirdPartyUserSetter[];
30
+ /** An app's opening link, which native's `getTags` merges into every event's tags. */
31
+ deepLink?: DeepLink;
19
32
  }
20
33
  interface Config {
21
34
  release: string;
@@ -28,6 +41,7 @@ interface Config {
28
41
  getHeaders: () => Record<string, string> | Promise<Record<string, string>>;
29
42
  thirdPartyTrackers: ThirdPartyTracker[];
30
43
  thirdPartyUserSetters: ThirdPartyUserSetter[];
44
+ deepLink: DeepLink | undefined;
31
45
  }
32
46
  interface Cache {
33
47
  tags: TrackTags | null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/setup/index.ts"],"mappings":";;;iBAGiB;EACf,UAAU;EACV,UAAU,aAAa;;iBAGR;EACf;EACA,SAAS;EACT;EACA,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,mBAAmB,yBAAyB,QAAQ;EACpD,qBAAqB;EACrB,wBAAwB;;UAGhB;EACR;EACA;EACA,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,kBAAkB,yBAAyB,QAAQ;EACnD,oBAAoB;EACpB,uBAAuB;;UAGf;EACR,MAAM;;qBAGK,OAAO;qBAKP,QAAQ;wBAcL,eAAe,MAAM"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/setup/index.ts"],"mappings":";;;iBAGiB;EACf,UAAU;EACV,UAAU,aAAa;;;;;;;iBAQR;;EAEf;;EAEA,eAAe,YAAY,QAAQ;;iBAGpB;EACf;EACA,SAAS;EACT;EACA,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,mBAAmB,yBAAyB,QAAQ;EACpD,qBAAqB;EACrB,wBAAwB;;EAExB,WAAW;;UAGH;EACR;EACA;EACA,SAAS;EACT,UAAU;EACV,aAAa;EACb,eAAe,YAAY,QAAQ;EACnC,4BAA4B;EAC5B,kBAAkB,yBAAyB,QAAQ;EACnD,oBAAoB;EACpB,uBAAuB;EACvB,UAAU;;UAGF;EACR,MAAM;;qBAGK,OAAO;qBAKP,QAAQ;wBAeL,eAAe,MAAM"}
@@ -10,7 +10,8 @@ const config = {
10
10
  getDeviceId: null,
11
11
  getHeaders: null,
12
12
  thirdPartyTrackers: [],
13
- thirdPartyUserSetters: []
13
+ thirdPartyUserSetters: [],
14
+ deepLink: void 0
14
15
  };
15
16
  function setupAnalytics(init) {
16
17
  config.release = init.release;
@@ -26,6 +27,12 @@ function setupAnalytics(init) {
26
27
  });
27
28
  config.thirdPartyTrackers = init.thirdPartyTrackers ?? [];
28
29
  config.thirdPartyUserSetters = init.thirdPartyUserSetters ?? [];
30
+ config.deepLink = init.deepLink;
31
+ try {
32
+ init.deepLink?.listen();
33
+ } catch (error) {
34
+ console.error("analytics deepLink.listen failed", error);
35
+ }
29
36
  }
30
37
  //#endregion
31
38
  export { cache, config, setupAnalytics };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/setup/index.ts"],"sourcesContent":["import type { Environment, Platform, ThirdPartyTracker, TrackTags } from '../track/types';\nimport type { ThirdPartyUserSetter } from '../visitor/types';\n\nexport interface Storage {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n}\n\nexport interface Options {\n release: string;\n storage: Storage;\n endpoint: string;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers?: ThirdPartyTracker[];\n thirdPartyUserSetters?: ThirdPartyUserSetter[];\n}\n\ninterface Config {\n release: string;\n endpoint: string;\n storage: Storage;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers: ThirdPartyTracker[];\n thirdPartyUserSetters: ThirdPartyUserSetter[];\n}\n\ninterface Cache {\n tags: TrackTags | null;\n}\n\nexport const cache: Cache = {\n tags: null,\n};\n\n// oxlint-disable typescript/no-non-null-assertion\nexport const config: Config = {\n endpoint: '',\n release: '0.0.0',\n storage: null!,\n platform: null!,\n environment: null!,\n getTags: null!,\n getDeviceId: null!,\n getHeaders: null!,\n thirdPartyTrackers: [],\n thirdPartyUserSetters: [],\n};\n// oxlint-enable typescript/no-non-null-assertion\n\nexport function setupAnalytics(init: Options) {\n config.release = init.release;\n config.storage = init.storage;\n config.platform = init.platform;\n config.environment = init.environment;\n config.endpoint = init.endpoint.endsWith('/') ? init.endpoint.slice(0, -1) : init.endpoint;\n config.getTags = init.getTags;\n config.getDeviceId = init.getDeviceId;\n config.getHeaders = async () => ({\n 'Content-Type': 'application/json',\n ...(await init.getHeaders?.()),\n });\n config.thirdPartyTrackers = init.thirdPartyTrackers ?? [];\n config.thirdPartyUserSetters = init.thirdPartyUserSetters ?? [];\n}\n"],"mappings":";AAsCA,MAAa,QAAe,EAC1B,MAAM,KACR;AAGA,MAAa,SAAiB;CAC5B,UAAU;CACV,SAAS;CACT,SAAS;CACT,UAAU;CACV,aAAa;CACb,SAAS;CACT,aAAa;CACb,YAAY;CACZ,oBAAoB,CAAC;CACrB,uBAAuB,CAAC;AAC1B;AAGA,SAAgB,eAAe,MAAe;CAC5C,OAAO,UAAU,KAAK;CACtB,OAAO,UAAU,KAAK;CACtB,OAAO,WAAW,KAAK;CACvB,OAAO,cAAc,KAAK;CAC1B,OAAO,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;CAClF,OAAO,UAAU,KAAK;CACtB,OAAO,cAAc,KAAK;CAC1B,OAAO,aAAa,aAAa;EAC/B,gBAAgB;EAChB,GAAI,MAAM,KAAK,aAAa;CAC9B;CACA,OAAO,qBAAqB,KAAK,sBAAsB,CAAC;CACxD,OAAO,wBAAwB,KAAK,yBAAyB,CAAC;AAChE"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/setup/index.ts"],"sourcesContent":["import type { Environment, Platform, ThirdPartyTracker, TrackTags } from '../track/types';\nimport type { ThirdPartyUserSetter } from '../visitor/types';\n\nexport interface Storage {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n}\n\n/**\n * The link that opened the current visit of an app — a universal link, an app link, a custom\n * scheme — whose URL, utm and click ids land the visit as a web page's URL does.\n * `@shware/analytics/native` provides one (`deepLink`).\n */\nexport interface DeepLink {\n /** Starts following the links that open the app; `setupAnalytics` calls it once. */\n listen: () => void;\n /** The opening link's tags (`page_location`, utm, click ids); empty without one. */\n getTags: () => TrackTags | Promise<TrackTags>;\n}\n\nexport interface Options {\n release: string;\n storage: Storage;\n endpoint: string;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers?: ThirdPartyTracker[];\n thirdPartyUserSetters?: ThirdPartyUserSetter[];\n /** An app's opening link, which native's `getTags` merges into every event's tags. */\n deepLink?: DeepLink;\n}\n\ninterface Config {\n release: string;\n endpoint: string;\n storage: Storage;\n platform: Platform;\n environment: Environment;\n getTags: () => TrackTags | Promise<TrackTags>;\n getDeviceId: () => string | Promise<string>;\n getHeaders: () => Record<string, string> | Promise<Record<string, string>>;\n thirdPartyTrackers: ThirdPartyTracker[];\n thirdPartyUserSetters: ThirdPartyUserSetter[];\n deepLink: DeepLink | undefined;\n}\n\ninterface Cache {\n tags: TrackTags | null;\n}\n\nexport const cache: Cache = {\n tags: null,\n};\n\n// oxlint-disable typescript/no-non-null-assertion\nexport const config: Config = {\n endpoint: '',\n release: '0.0.0',\n storage: null!,\n platform: null!,\n environment: null!,\n getTags: null!,\n getDeviceId: null!,\n getHeaders: null!,\n thirdPartyTrackers: [],\n thirdPartyUserSetters: [],\n deepLink: undefined,\n};\n// oxlint-enable typescript/no-non-null-assertion\n\nexport function setupAnalytics(init: Options) {\n config.release = init.release;\n config.storage = init.storage;\n config.platform = init.platform;\n config.environment = init.environment;\n config.endpoint = init.endpoint.endsWith('/') ? init.endpoint.slice(0, -1) : init.endpoint;\n config.getTags = init.getTags;\n config.getDeviceId = init.getDeviceId;\n config.getHeaders = async () => ({\n 'Content-Type': 'application/json',\n ...(await init.getHeaders?.()),\n });\n config.thirdPartyTrackers = init.thirdPartyTrackers ?? [];\n config.thirdPartyUserSetters = init.thirdPartyUserSetters ?? [];\n config.deepLink = init.deepLink;\n // Logged, not thrown: the links are worth less than the setup they would break.\n try {\n init.deepLink?.listen();\n } catch (error) {\n console.error('analytics deepLink.listen failed', error);\n }\n}\n"],"mappings":";AAqDA,MAAa,QAAe,EAC1B,MAAM,KACR;AAGA,MAAa,SAAiB;CAC5B,UAAU;CACV,SAAS;CACT,SAAS;CACT,UAAU;CACV,aAAa;CACb,SAAS;CACT,aAAa;CACb,YAAY;CACZ,oBAAoB,CAAC;CACrB,uBAAuB,CAAC;CACxB,UAAU,KAAA;AACZ;AAGA,SAAgB,eAAe,MAAe;CAC5C,OAAO,UAAU,KAAK;CACtB,OAAO,UAAU,KAAK;CACtB,OAAO,WAAW,KAAK;CACvB,OAAO,cAAc,KAAK;CAC1B,OAAO,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;CAClF,OAAO,UAAU,KAAK;CACtB,OAAO,cAAc,KAAK;CAC1B,OAAO,aAAa,aAAa;EAC/B,gBAAgB;EAChB,GAAI,MAAM,KAAK,aAAa;CAC9B;CACA,OAAO,qBAAqB,KAAK,sBAAsB,CAAC;CACxD,OAAO,wBAAwB,KAAK,yBAAyB,CAAC;CAC9D,OAAO,WAAW,KAAK;CAEvB,IAAI;EACF,KAAK,UAAU,OAAO;CACxB,SAAS,OAAO;EACd,QAAQ,MAAM,oCAAoC,KAAK;CACzD;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shware/analytics",
3
- "version": "11.6.0",
3
+ "version": "11.8.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,6 +21,16 @@
21
21
  "default": "./dist/index.cjs"
22
22
  }
23
23
  },
24
+ "./ads": {
25
+ "import": {
26
+ "types": "./dist/ads/index.d.mts",
27
+ "default": "./dist/ads/index.mjs"
28
+ },
29
+ "require": {
30
+ "types": "./dist/ads/index.d.cts",
31
+ "default": "./dist/ads/index.cjs"
32
+ }
33
+ },
24
34
  "./attribution": {
25
35
  "import": {
26
36
  "types": "./dist/attribution/index.d.mts",