@shware/analytics 3.5.2 → 3.6.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 (49) hide show
  1. package/dist/server/index.cjs +3 -0
  2. package/dist/server/index.cjs.map +1 -1
  3. package/dist/server/index.d.cts +2 -0
  4. package/dist/server/index.d.ts +2 -0
  5. package/dist/server/index.mjs +2 -0
  6. package/dist/server/index.mjs.map +1 -1
  7. package/dist/server/openai-conversions-api.cjs +107 -0
  8. package/dist/server/openai-conversions-api.cjs.map +1 -0
  9. package/dist/server/openai-conversions-api.d.cts +47 -0
  10. package/dist/server/openai-conversions-api.d.ts +47 -0
  11. package/dist/server/openai-conversions-api.mjs +81 -0
  12. package/dist/server/openai-conversions-api.mjs.map +1 -0
  13. package/dist/tanstack/index.cjs +28 -0
  14. package/dist/tanstack/index.cjs.map +1 -1
  15. package/dist/tanstack/index.d.cts +2 -1
  16. package/dist/tanstack/index.d.ts +2 -1
  17. package/dist/tanstack/index.mjs +28 -0
  18. package/dist/tanstack/index.mjs.map +1 -1
  19. package/dist/third-parties/google-analytics.cjs.map +1 -1
  20. package/dist/third-parties/google-analytics.mjs.map +1 -1
  21. package/dist/third-parties/index.cjs +5 -0
  22. package/dist/third-parties/index.cjs.map +1 -1
  23. package/dist/third-parties/index.d.cts +2 -0
  24. package/dist/third-parties/index.d.ts +2 -0
  25. package/dist/third-parties/index.mjs +3 -0
  26. package/dist/third-parties/index.mjs.map +1 -1
  27. package/dist/third-parties/linkedin-insight-tag.cjs.map +1 -1
  28. package/dist/third-parties/linkedin-insight-tag.mjs.map +1 -1
  29. package/dist/third-parties/meta-pixel.cjs.map +1 -1
  30. package/dist/third-parties/meta-pixel.mjs.map +1 -1
  31. package/dist/third-parties/openai-pixel.cjs +78 -0
  32. package/dist/third-parties/openai-pixel.cjs.map +1 -0
  33. package/dist/third-parties/openai-pixel.d.cts +23 -0
  34. package/dist/third-parties/openai-pixel.d.ts +23 -0
  35. package/dist/third-parties/openai-pixel.mjs +52 -0
  36. package/dist/third-parties/openai-pixel.mjs.map +1 -0
  37. package/dist/third-parties/reddit-pixel.cjs.map +1 -1
  38. package/dist/third-parties/reddit-pixel.mjs.map +1 -1
  39. package/dist/track/gtag.cjs.map +1 -1
  40. package/dist/track/gtag.d.cts +45 -12
  41. package/dist/track/gtag.d.ts +45 -12
  42. package/dist/track/gtag.mjs.map +1 -1
  43. package/dist/track/oaiq.cjs +155 -0
  44. package/dist/track/oaiq.cjs.map +1 -0
  45. package/dist/track/oaiq.d.cts +110 -0
  46. package/dist/track/oaiq.d.ts +110 -0
  47. package/dist/track/oaiq.mjs +128 -0
  48. package/dist/track/oaiq.mjs.map +1 -0
  49. package/package.json +1 -1
@@ -22,16 +22,19 @@ var server_exports = {};
22
22
  __export(server_exports, {
23
23
  sendLinkedinEvents: () => import_linkedin_conversions_api.sendEvents,
24
24
  sendMetaEvents: () => import_meta_conversions_api.sendEvents,
25
+ sendOpenAIEvents: () => import_openai_conversions_api.sendEvents,
25
26
  sendRedditEvents: () => import_reddit_conversions_api.sendEvents
26
27
  });
27
28
  module.exports = __toCommonJS(server_exports);
28
29
  var import_meta_conversions_api = require("./meta-conversions-api.cjs");
29
30
  var import_reddit_conversions_api = require("./reddit-conversions-api.cjs");
30
31
  var import_linkedin_conversions_api = require("./linkedin-conversions-api.cjs");
32
+ var import_openai_conversions_api = require("./openai-conversions-api.cjs");
31
33
  // Annotate the CommonJS export names for ESM import in node:
32
34
  0 && (module.exports = {
33
35
  sendLinkedinEvents,
34
36
  sendMetaEvents,
37
+ sendOpenAIEvents,
35
38
  sendRedditEvents
36
39
  });
37
40
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["export { sendEvents as sendMetaEvents } from './meta-conversions-api';\nexport { sendEvents as sendRedditEvents } from './reddit-conversions-api';\nexport { sendEvents as sendLinkedinEvents } from './linkedin-conversions-api';\n\nexport type { LinkedinConversionConfig } from './linkedin-conversions-api';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAA6C;AAC7C,oCAA+C;AAC/C,sCAAiD;","names":[]}
1
+ {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["export { sendEvents as sendMetaEvents } from './meta-conversions-api';\nexport { sendEvents as sendRedditEvents } from './reddit-conversions-api';\nexport { sendEvents as sendLinkedinEvents } from './linkedin-conversions-api';\nexport { sendEvents as sendOpenAIEvents } from './openai-conversions-api';\n\nexport type { LinkedinConversionConfig } from './linkedin-conversions-api';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAA6C;AAC7C,oCAA+C;AAC/C,sCAAiD;AACjD,oCAA+C;","names":[]}
@@ -1,7 +1,9 @@
1
1
  export { sendEvents as sendMetaEvents } from './meta-conversions-api.cjs';
2
2
  export { sendEvents as sendRedditEvents } from './reddit-conversions-api.cjs';
3
3
  export { LinkedinConversionConfig, sendEvents as sendLinkedinEvents } from './linkedin-conversions-api.cjs';
4
+ export { sendEvents as sendOpenAIEvents } from './openai-conversions-api.cjs';
4
5
  import 'facebook-nodejs-business-sdk';
5
6
  import '../track/types.cjs';
6
7
  import '../track/gtag.cjs';
7
8
  import '../track/rdt.cjs';
9
+ import '../track/oaiq.cjs';
@@ -1,7 +1,9 @@
1
1
  export { sendEvents as sendMetaEvents } from './meta-conversions-api.js';
2
2
  export { sendEvents as sendRedditEvents } from './reddit-conversions-api.js';
3
3
  export { LinkedinConversionConfig, sendEvents as sendLinkedinEvents } from './linkedin-conversions-api.js';
4
+ export { sendEvents as sendOpenAIEvents } from './openai-conversions-api.js';
4
5
  import 'facebook-nodejs-business-sdk';
5
6
  import '../track/types.js';
6
7
  import '../track/gtag.js';
7
8
  import '../track/rdt.js';
9
+ import '../track/oaiq.js';
@@ -2,9 +2,11 @@
2
2
  import { sendEvents } from "./meta-conversions-api.mjs";
3
3
  import { sendEvents as sendEvents2 } from "./reddit-conversions-api.mjs";
4
4
  import { sendEvents as sendEvents3 } from "./linkedin-conversions-api.mjs";
5
+ import { sendEvents as sendEvents4 } from "./openai-conversions-api.mjs";
5
6
  export {
6
7
  sendEvents3 as sendLinkedinEvents,
7
8
  sendEvents as sendMetaEvents,
9
+ sendEvents4 as sendOpenAIEvents,
8
10
  sendEvents2 as sendRedditEvents
9
11
  };
10
12
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["export { sendEvents as sendMetaEvents } from './meta-conversions-api';\nexport { sendEvents as sendRedditEvents } from './reddit-conversions-api';\nexport { sendEvents as sendLinkedinEvents } from './linkedin-conversions-api';\n\nexport type { LinkedinConversionConfig } from './linkedin-conversions-api';\n"],"mappings":";AAAA,SAAuB,kBAAsB;AAC7C,SAAuB,cAAdA,mBAAsC;AAC/C,SAAuB,cAAdA,mBAAwC;","names":["sendEvents"]}
1
+ {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["export { sendEvents as sendMetaEvents } from './meta-conversions-api';\nexport { sendEvents as sendRedditEvents } from './reddit-conversions-api';\nexport { sendEvents as sendLinkedinEvents } from './linkedin-conversions-api';\nexport { sendEvents as sendOpenAIEvents } from './openai-conversions-api';\n\nexport type { LinkedinConversionConfig } from './linkedin-conversions-api';\n"],"mappings":";AAAA,SAAuB,kBAAsB;AAC7C,SAAuB,cAAdA,mBAAsC;AAC/C,SAAuB,cAAdA,mBAAwC;AACjD,SAAuB,cAAdA,mBAAsC;","names":["sendEvents"]}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/server/openai-conversions-api.ts
21
+ var openai_conversions_api_exports = {};
22
+ __export(openai_conversions_api_exports, {
23
+ getServerEvent: () => getServerEvent,
24
+ sendEvents: () => sendEvents
25
+ });
26
+ module.exports = __toCommonJS(openai_conversions_api_exports);
27
+ var import_crypto = require("crypto");
28
+ var import_utils = require("@shware/utils");
29
+ var import_ignored_events = require("../third-parties/ignored-events.cjs");
30
+ var import_oaiq = require("../track/oaiq.cjs");
31
+ var import_field = require("../utils/field.cjs");
32
+ var ENDPOINT = "https://bzr.openai.com/v1/events";
33
+ function sha256(value) {
34
+ return (0, import_crypto.createHash)("sha256").update(value).digest("hex");
35
+ }
36
+ function mapActionSource(source) {
37
+ switch (source) {
38
+ case "web":
39
+ return "web";
40
+ case "app":
41
+ return "mobile_app";
42
+ case "offline":
43
+ return "offline";
44
+ default:
45
+ return void 0;
46
+ }
47
+ }
48
+ function getUser(data) {
49
+ var _a, _b, _c;
50
+ const email = (_a = (0, import_field.getFirst)(data.email)) == null ? void 0 : _a.trim().toLowerCase();
51
+ const address = (0, import_field.getFirst)(data.address);
52
+ const user = {
53
+ email_sha256: email ? sha256(email) : void 0,
54
+ external_id_sha256: data.user_id ? sha256(data.user_id) : void 0,
55
+ country: (_b = address == null ? void 0 : address.country) == null ? void 0 : _b.trim().toUpperCase(),
56
+ city: (_c = address == null ? void 0 : address.city) == null ? void 0 : _c.trim().toLowerCase(),
57
+ zip_code: address == null ? void 0 : address.postal_code,
58
+ ip_address: data.ip_address,
59
+ user_agent: data.user_agent
60
+ };
61
+ return Object.values(user).some((value) => value !== void 0) ? user : void 0;
62
+ }
63
+ function getServerEvent(event, data) {
64
+ const { type, data: eventData } = (0, import_oaiq.mapOAIEvent)(event.name, event.properties);
65
+ return {
66
+ id: event.tags.idempotency_key ?? event.id.toString(),
67
+ type,
68
+ // For custom events the original track name is the OpenAI custom_event_name; this matches
69
+ // the browser pixel so the two deduplicate. Standard events omit it.
70
+ custom_event_name: type === "custom" ? event.name : void 0,
71
+ timestamp_ms: Date.now(),
72
+ source_url: event.tags.source_url,
73
+ action_source: mapActionSource(event.tags.source),
74
+ user: getUser(data),
75
+ data: eventData
76
+ };
77
+ }
78
+ async function sendEvents(apiKey, pixelId, events, data = {}, validateOnly = false) {
79
+ const dto = {
80
+ validate_only: validateOnly,
81
+ events: events.filter((event) => !import_ignored_events.IGNORED_EVENTS.includes(event.name)).map((event) => getServerEvent(event, data))
82
+ };
83
+ if (dto.events.length === 0) return;
84
+ try {
85
+ const response = await (0, import_utils.fetch)(`${ENDPOINT}?pid=${pixelId}`, {
86
+ method: "POST",
87
+ headers: {
88
+ "Content-Type": "application/json",
89
+ Accept: "application/json",
90
+ Authorization: `Bearer ${apiKey}`
91
+ },
92
+ body: JSON.stringify(dto)
93
+ });
94
+ if (response.ok) return;
95
+ const { status } = response;
96
+ const message = await response.text();
97
+ console.error(`Failed to send OpenAI conversion, status: ${status}, body: ${message}`);
98
+ } catch (error) {
99
+ console.error("Failed to send OpenAI conversion, network error:", error);
100
+ }
101
+ }
102
+ // Annotate the CommonJS export names for ESM import in node:
103
+ 0 && (module.exports = {
104
+ getServerEvent,
105
+ sendEvents
106
+ });
107
+ //# sourceMappingURL=openai-conversions-api.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/openai-conversions-api.ts"],"sourcesContent":["/**\n * OpenAI Conversions API\n * https://developers.openai.com/ads/conversions-api\n * https://developers.openai.com/ads/supported-events\n */\nimport { createHash } from 'crypto';\nimport { fetch } from '@shware/utils';\nimport { IGNORED_EVENTS } from '../third-parties/ignored-events';\nimport { type EventData, mapOAIEvent } from '../track/oaiq';\nimport type { TrackEvent, TrackTags, UserProvidedData } from '../track/types';\nimport { getFirst } from '../utils/field';\n\nconst ENDPOINT = 'https://bzr.openai.com/v1/events';\n\ntype ActionSource =\n | 'web'\n | 'mobile_app'\n | 'offline'\n | 'physical_store'\n | 'phone_call'\n | 'email'\n | 'other';\n\n/**\n * User/identity fields. Email and external id must be sent as lowercase 64-char SHA-256 hex\n * strings; geographic, IP, and user-agent fields are sent as raw values.\n */\nexport interface OpenAIUser {\n email_sha256?: string;\n external_id_sha256?: string;\n /** Two-letter ISO 3166-1 country code (e.g. \"US\"). */\n country?: string;\n city?: string;\n zip_code?: string;\n ip_address?: string;\n user_agent?: string;\n}\n\nexport interface OpenAIEvent {\n /** Unique event id; combined with `type` for deduplication against pixel events. */\n id: string;\n /** Standard event name or `custom`. */\n type: string;\n /** Required when `type` is `custom`. */\n custom_event_name?: string;\n /** Event timestamp in ms; must be within 7 days and no more than 10 minutes in the future. */\n timestamp_ms: number;\n /** Required for `action_source: \"web\"`. */\n source_url?: string;\n action_source?: ActionSource;\n /** OpenAI-provided privacy-preserving identifier. */\n oppref?: string;\n /** When true, opts the event out of personalization. */\n opt_out?: boolean;\n user?: OpenAIUser;\n data: EventData;\n}\n\nexport interface CreateOpenAIEventsDTO {\n /** When true, validates the events without persisting them. */\n validate_only?: boolean;\n events: OpenAIEvent[];\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction mapActionSource(source: TrackTags['source']): ActionSource | undefined {\n switch (source) {\n case 'web':\n return 'web';\n case 'app':\n return 'mobile_app';\n case 'offline':\n return 'offline';\n default:\n return undefined;\n }\n}\n\nfunction getUser(data: UserProvidedData): OpenAIUser | undefined {\n const email = getFirst(data.email)?.trim().toLowerCase();\n const address = getFirst(data.address);\n\n const user: OpenAIUser = {\n email_sha256: email ? sha256(email) : undefined,\n external_id_sha256: data.user_id ? sha256(data.user_id) : undefined,\n country: address?.country?.trim().toUpperCase(),\n city: address?.city?.trim().toLowerCase(),\n zip_code: address?.postal_code,\n ip_address: data.ip_address,\n user_agent: data.user_agent,\n };\n\n return Object.values(user).some((value) => value !== undefined) ? user : undefined;\n}\n\nexport function getServerEvent(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n event: TrackEvent<any>,\n data: UserProvidedData\n): OpenAIEvent {\n const { type, data: eventData } = mapOAIEvent(event.name, event.properties);\n\n return {\n id: event.tags.idempotency_key ?? event.id.toString(),\n type,\n // For custom events the original track name is the OpenAI custom_event_name; this matches\n // the browser pixel so the two deduplicate. Standard events omit it.\n custom_event_name: type === 'custom' ? event.name : undefined,\n timestamp_ms: Date.now(),\n source_url: event.tags.source_url,\n action_source: mapActionSource(event.tags.source),\n user: getUser(data),\n data: eventData,\n };\n}\n\nexport async function sendEvents(\n apiKey: string,\n pixelId: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n events: TrackEvent<any>[],\n data: UserProvidedData = {},\n validateOnly = false\n) {\n const dto: CreateOpenAIEventsDTO = {\n validate_only: validateOnly,\n events: events\n .filter((event) => !IGNORED_EVENTS.includes(event.name))\n .map((event) => getServerEvent(event, data)),\n };\n\n if (dto.events.length === 0) return;\n\n try {\n const response = await fetch(`${ENDPOINT}?pid=${pixelId}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(dto),\n });\n\n if (response.ok) return;\n const { status } = response;\n const message = await response.text();\n console.error(`Failed to send OpenAI conversion, status: ${status}, body: ${message}`);\n } catch (error) {\n console.error('Failed to send OpenAI conversion, network error:', error);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,oBAA2B;AAC3B,mBAAsB;AACtB,4BAA+B;AAC/B,kBAA4C;AAE5C,mBAAyB;AAEzB,IAAM,WAAW;AAoDjB,SAAS,OAAO,OAAuB;AACrC,aAAO,0BAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEA,SAAS,gBAAgB,QAAuD;AAC9E,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,QAAQ,MAAgD;AAjFjE;AAkFE,QAAM,SAAQ,gCAAS,KAAK,KAAK,MAAnB,mBAAsB,OAAO;AAC3C,QAAM,cAAU,uBAAS,KAAK,OAAO;AAErC,QAAM,OAAmB;AAAA,IACvB,cAAc,QAAQ,OAAO,KAAK,IAAI;AAAA,IACtC,oBAAoB,KAAK,UAAU,OAAO,KAAK,OAAO,IAAI;AAAA,IAC1D,UAAS,wCAAS,YAAT,mBAAkB,OAAO;AAAA,IAClC,OAAM,wCAAS,SAAT,mBAAe,OAAO;AAAA,IAC5B,UAAU,mCAAS;AAAA,IACnB,YAAY,KAAK;AAAA,IACjB,YAAY,KAAK;AAAA,EACnB;AAEA,SAAO,OAAO,OAAO,IAAI,EAAE,KAAK,CAAC,UAAU,UAAU,MAAS,IAAI,OAAO;AAC3E;AAEO,SAAS,eAEd,OACA,MACa;AACb,QAAM,EAAE,MAAM,MAAM,UAAU,QAAI,yBAAY,MAAM,MAAM,MAAM,UAAU;AAE1E,SAAO;AAAA,IACL,IAAI,MAAM,KAAK,mBAAmB,MAAM,GAAG,SAAS;AAAA,IACpD;AAAA;AAAA;AAAA,IAGA,mBAAmB,SAAS,WAAW,MAAM,OAAO;AAAA,IACpD,cAAc,KAAK,IAAI;AAAA,IACvB,YAAY,MAAM,KAAK;AAAA,IACvB,eAAe,gBAAgB,MAAM,KAAK,MAAM;AAAA,IAChD,MAAM,QAAQ,IAAI;AAAA,IAClB,MAAM;AAAA,EACR;AACF;AAEA,eAAsB,WACpB,QACA,SAEA,QACA,OAAyB,CAAC,GAC1B,eAAe,OACf;AACA,QAAM,MAA6B;AAAA,IACjC,eAAe;AAAA,IACf,QAAQ,OACL,OAAO,CAAC,UAAU,CAAC,qCAAe,SAAS,MAAM,IAAI,CAAC,EACtD,IAAI,CAAC,UAAU,eAAe,OAAO,IAAI,CAAC;AAAA,EAC/C;AAEA,MAAI,IAAI,OAAO,WAAW,EAAG;AAE7B,MAAI;AACF,UAAM,WAAW,UAAM,oBAAM,GAAG,QAAQ,QAAQ,OAAO,IAAI;AAAA,MACzD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,GAAG;AAAA,IAC1B,CAAC;AAED,QAAI,SAAS,GAAI;AACjB,UAAM,EAAE,OAAO,IAAI;AACnB,UAAM,UAAU,MAAM,SAAS,KAAK;AACpC,YAAQ,MAAM,6CAA6C,MAAM,WAAW,OAAO,EAAE;AAAA,EACvF,SAAS,OAAO;AACd,YAAQ,MAAM,oDAAoD,KAAK;AAAA,EACzE;AACF;","names":[]}
@@ -0,0 +1,47 @@
1
+ import { EventData } from '../track/oaiq.cjs';
2
+ import { TrackEvent, UserProvidedData } from '../track/types.cjs';
3
+ import '../track/gtag.cjs';
4
+
5
+ type ActionSource = 'web' | 'mobile_app' | 'offline' | 'physical_store' | 'phone_call' | 'email' | 'other';
6
+ /**
7
+ * User/identity fields. Email and external id must be sent as lowercase 64-char SHA-256 hex
8
+ * strings; geographic, IP, and user-agent fields are sent as raw values.
9
+ */
10
+ interface OpenAIUser {
11
+ email_sha256?: string;
12
+ external_id_sha256?: string;
13
+ /** Two-letter ISO 3166-1 country code (e.g. "US"). */
14
+ country?: string;
15
+ city?: string;
16
+ zip_code?: string;
17
+ ip_address?: string;
18
+ user_agent?: string;
19
+ }
20
+ interface OpenAIEvent {
21
+ /** Unique event id; combined with `type` for deduplication against pixel events. */
22
+ id: string;
23
+ /** Standard event name or `custom`. */
24
+ type: string;
25
+ /** Required when `type` is `custom`. */
26
+ custom_event_name?: string;
27
+ /** Event timestamp in ms; must be within 7 days and no more than 10 minutes in the future. */
28
+ timestamp_ms: number;
29
+ /** Required for `action_source: "web"`. */
30
+ source_url?: string;
31
+ action_source?: ActionSource;
32
+ /** OpenAI-provided privacy-preserving identifier. */
33
+ oppref?: string;
34
+ /** When true, opts the event out of personalization. */
35
+ opt_out?: boolean;
36
+ user?: OpenAIUser;
37
+ data: EventData;
38
+ }
39
+ interface CreateOpenAIEventsDTO {
40
+ /** When true, validates the events without persisting them. */
41
+ validate_only?: boolean;
42
+ events: OpenAIEvent[];
43
+ }
44
+ declare function getServerEvent(event: TrackEvent<any>, data: UserProvidedData): OpenAIEvent;
45
+ declare function sendEvents(apiKey: string, pixelId: string, events: TrackEvent<any>[], data?: UserProvidedData, validateOnly?: boolean): Promise<void>;
46
+
47
+ export { type CreateOpenAIEventsDTO, type OpenAIEvent, type OpenAIUser, getServerEvent, sendEvents };
@@ -0,0 +1,47 @@
1
+ import { EventData } from '../track/oaiq.js';
2
+ import { TrackEvent, UserProvidedData } from '../track/types.js';
3
+ import '../track/gtag.js';
4
+
5
+ type ActionSource = 'web' | 'mobile_app' | 'offline' | 'physical_store' | 'phone_call' | 'email' | 'other';
6
+ /**
7
+ * User/identity fields. Email and external id must be sent as lowercase 64-char SHA-256 hex
8
+ * strings; geographic, IP, and user-agent fields are sent as raw values.
9
+ */
10
+ interface OpenAIUser {
11
+ email_sha256?: string;
12
+ external_id_sha256?: string;
13
+ /** Two-letter ISO 3166-1 country code (e.g. "US"). */
14
+ country?: string;
15
+ city?: string;
16
+ zip_code?: string;
17
+ ip_address?: string;
18
+ user_agent?: string;
19
+ }
20
+ interface OpenAIEvent {
21
+ /** Unique event id; combined with `type` for deduplication against pixel events. */
22
+ id: string;
23
+ /** Standard event name or `custom`. */
24
+ type: string;
25
+ /** Required when `type` is `custom`. */
26
+ custom_event_name?: string;
27
+ /** Event timestamp in ms; must be within 7 days and no more than 10 minutes in the future. */
28
+ timestamp_ms: number;
29
+ /** Required for `action_source: "web"`. */
30
+ source_url?: string;
31
+ action_source?: ActionSource;
32
+ /** OpenAI-provided privacy-preserving identifier. */
33
+ oppref?: string;
34
+ /** When true, opts the event out of personalization. */
35
+ opt_out?: boolean;
36
+ user?: OpenAIUser;
37
+ data: EventData;
38
+ }
39
+ interface CreateOpenAIEventsDTO {
40
+ /** When true, validates the events without persisting them. */
41
+ validate_only?: boolean;
42
+ events: OpenAIEvent[];
43
+ }
44
+ declare function getServerEvent(event: TrackEvent<any>, data: UserProvidedData): OpenAIEvent;
45
+ declare function sendEvents(apiKey: string, pixelId: string, events: TrackEvent<any>[], data?: UserProvidedData, validateOnly?: boolean): Promise<void>;
46
+
47
+ export { type CreateOpenAIEventsDTO, type OpenAIEvent, type OpenAIUser, getServerEvent, sendEvents };
@@ -0,0 +1,81 @@
1
+ // src/server/openai-conversions-api.ts
2
+ import { createHash } from "crypto";
3
+ import { fetch } from "@shware/utils";
4
+ import { IGNORED_EVENTS } from "../third-parties/ignored-events.mjs";
5
+ import { mapOAIEvent } from "../track/oaiq.mjs";
6
+ import { getFirst } from "../utils/field.mjs";
7
+ var ENDPOINT = "https://bzr.openai.com/v1/events";
8
+ function sha256(value) {
9
+ return createHash("sha256").update(value).digest("hex");
10
+ }
11
+ function mapActionSource(source) {
12
+ switch (source) {
13
+ case "web":
14
+ return "web";
15
+ case "app":
16
+ return "mobile_app";
17
+ case "offline":
18
+ return "offline";
19
+ default:
20
+ return void 0;
21
+ }
22
+ }
23
+ function getUser(data) {
24
+ var _a, _b, _c;
25
+ const email = (_a = getFirst(data.email)) == null ? void 0 : _a.trim().toLowerCase();
26
+ const address = getFirst(data.address);
27
+ const user = {
28
+ email_sha256: email ? sha256(email) : void 0,
29
+ external_id_sha256: data.user_id ? sha256(data.user_id) : void 0,
30
+ country: (_b = address == null ? void 0 : address.country) == null ? void 0 : _b.trim().toUpperCase(),
31
+ city: (_c = address == null ? void 0 : address.city) == null ? void 0 : _c.trim().toLowerCase(),
32
+ zip_code: address == null ? void 0 : address.postal_code,
33
+ ip_address: data.ip_address,
34
+ user_agent: data.user_agent
35
+ };
36
+ return Object.values(user).some((value) => value !== void 0) ? user : void 0;
37
+ }
38
+ function getServerEvent(event, data) {
39
+ const { type, data: eventData } = mapOAIEvent(event.name, event.properties);
40
+ return {
41
+ id: event.tags.idempotency_key ?? event.id.toString(),
42
+ type,
43
+ // For custom events the original track name is the OpenAI custom_event_name; this matches
44
+ // the browser pixel so the two deduplicate. Standard events omit it.
45
+ custom_event_name: type === "custom" ? event.name : void 0,
46
+ timestamp_ms: Date.now(),
47
+ source_url: event.tags.source_url,
48
+ action_source: mapActionSource(event.tags.source),
49
+ user: getUser(data),
50
+ data: eventData
51
+ };
52
+ }
53
+ async function sendEvents(apiKey, pixelId, events, data = {}, validateOnly = false) {
54
+ const dto = {
55
+ validate_only: validateOnly,
56
+ events: events.filter((event) => !IGNORED_EVENTS.includes(event.name)).map((event) => getServerEvent(event, data))
57
+ };
58
+ if (dto.events.length === 0) return;
59
+ try {
60
+ const response = await fetch(`${ENDPOINT}?pid=${pixelId}`, {
61
+ method: "POST",
62
+ headers: {
63
+ "Content-Type": "application/json",
64
+ Accept: "application/json",
65
+ Authorization: `Bearer ${apiKey}`
66
+ },
67
+ body: JSON.stringify(dto)
68
+ });
69
+ if (response.ok) return;
70
+ const { status } = response;
71
+ const message = await response.text();
72
+ console.error(`Failed to send OpenAI conversion, status: ${status}, body: ${message}`);
73
+ } catch (error) {
74
+ console.error("Failed to send OpenAI conversion, network error:", error);
75
+ }
76
+ }
77
+ export {
78
+ getServerEvent,
79
+ sendEvents
80
+ };
81
+ //# sourceMappingURL=openai-conversions-api.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/openai-conversions-api.ts"],"sourcesContent":["/**\n * OpenAI Conversions API\n * https://developers.openai.com/ads/conversions-api\n * https://developers.openai.com/ads/supported-events\n */\nimport { createHash } from 'crypto';\nimport { fetch } from '@shware/utils';\nimport { IGNORED_EVENTS } from '../third-parties/ignored-events';\nimport { type EventData, mapOAIEvent } from '../track/oaiq';\nimport type { TrackEvent, TrackTags, UserProvidedData } from '../track/types';\nimport { getFirst } from '../utils/field';\n\nconst ENDPOINT = 'https://bzr.openai.com/v1/events';\n\ntype ActionSource =\n | 'web'\n | 'mobile_app'\n | 'offline'\n | 'physical_store'\n | 'phone_call'\n | 'email'\n | 'other';\n\n/**\n * User/identity fields. Email and external id must be sent as lowercase 64-char SHA-256 hex\n * strings; geographic, IP, and user-agent fields are sent as raw values.\n */\nexport interface OpenAIUser {\n email_sha256?: string;\n external_id_sha256?: string;\n /** Two-letter ISO 3166-1 country code (e.g. \"US\"). */\n country?: string;\n city?: string;\n zip_code?: string;\n ip_address?: string;\n user_agent?: string;\n}\n\nexport interface OpenAIEvent {\n /** Unique event id; combined with `type` for deduplication against pixel events. */\n id: string;\n /** Standard event name or `custom`. */\n type: string;\n /** Required when `type` is `custom`. */\n custom_event_name?: string;\n /** Event timestamp in ms; must be within 7 days and no more than 10 minutes in the future. */\n timestamp_ms: number;\n /** Required for `action_source: \"web\"`. */\n source_url?: string;\n action_source?: ActionSource;\n /** OpenAI-provided privacy-preserving identifier. */\n oppref?: string;\n /** When true, opts the event out of personalization. */\n opt_out?: boolean;\n user?: OpenAIUser;\n data: EventData;\n}\n\nexport interface CreateOpenAIEventsDTO {\n /** When true, validates the events without persisting them. */\n validate_only?: boolean;\n events: OpenAIEvent[];\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction mapActionSource(source: TrackTags['source']): ActionSource | undefined {\n switch (source) {\n case 'web':\n return 'web';\n case 'app':\n return 'mobile_app';\n case 'offline':\n return 'offline';\n default:\n return undefined;\n }\n}\n\nfunction getUser(data: UserProvidedData): OpenAIUser | undefined {\n const email = getFirst(data.email)?.trim().toLowerCase();\n const address = getFirst(data.address);\n\n const user: OpenAIUser = {\n email_sha256: email ? sha256(email) : undefined,\n external_id_sha256: data.user_id ? sha256(data.user_id) : undefined,\n country: address?.country?.trim().toUpperCase(),\n city: address?.city?.trim().toLowerCase(),\n zip_code: address?.postal_code,\n ip_address: data.ip_address,\n user_agent: data.user_agent,\n };\n\n return Object.values(user).some((value) => value !== undefined) ? user : undefined;\n}\n\nexport function getServerEvent(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n event: TrackEvent<any>,\n data: UserProvidedData\n): OpenAIEvent {\n const { type, data: eventData } = mapOAIEvent(event.name, event.properties);\n\n return {\n id: event.tags.idempotency_key ?? event.id.toString(),\n type,\n // For custom events the original track name is the OpenAI custom_event_name; this matches\n // the browser pixel so the two deduplicate. Standard events omit it.\n custom_event_name: type === 'custom' ? event.name : undefined,\n timestamp_ms: Date.now(),\n source_url: event.tags.source_url,\n action_source: mapActionSource(event.tags.source),\n user: getUser(data),\n data: eventData,\n };\n}\n\nexport async function sendEvents(\n apiKey: string,\n pixelId: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n events: TrackEvent<any>[],\n data: UserProvidedData = {},\n validateOnly = false\n) {\n const dto: CreateOpenAIEventsDTO = {\n validate_only: validateOnly,\n events: events\n .filter((event) => !IGNORED_EVENTS.includes(event.name))\n .map((event) => getServerEvent(event, data)),\n };\n\n if (dto.events.length === 0) return;\n\n try {\n const response = await fetch(`${ENDPOINT}?pid=${pixelId}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(dto),\n });\n\n if (response.ok) return;\n const { status } = response;\n const message = await response.text();\n console.error(`Failed to send OpenAI conversion, status: ${status}, body: ${message}`);\n } catch (error) {\n console.error('Failed to send OpenAI conversion, network error:', error);\n }\n}\n"],"mappings":";AAKA,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB,SAAS,sBAAsB;AAC/B,SAAyB,mBAAmB;AAE5C,SAAS,gBAAgB;AAEzB,IAAM,WAAW;AAoDjB,SAAS,OAAO,OAAuB;AACrC,SAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEA,SAAS,gBAAgB,QAAuD;AAC9E,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,QAAQ,MAAgD;AAjFjE;AAkFE,QAAM,SAAQ,cAAS,KAAK,KAAK,MAAnB,mBAAsB,OAAO;AAC3C,QAAM,UAAU,SAAS,KAAK,OAAO;AAErC,QAAM,OAAmB;AAAA,IACvB,cAAc,QAAQ,OAAO,KAAK,IAAI;AAAA,IACtC,oBAAoB,KAAK,UAAU,OAAO,KAAK,OAAO,IAAI;AAAA,IAC1D,UAAS,wCAAS,YAAT,mBAAkB,OAAO;AAAA,IAClC,OAAM,wCAAS,SAAT,mBAAe,OAAO;AAAA,IAC5B,UAAU,mCAAS;AAAA,IACnB,YAAY,KAAK;AAAA,IACjB,YAAY,KAAK;AAAA,EACnB;AAEA,SAAO,OAAO,OAAO,IAAI,EAAE,KAAK,CAAC,UAAU,UAAU,MAAS,IAAI,OAAO;AAC3E;AAEO,SAAS,eAEd,OACA,MACa;AACb,QAAM,EAAE,MAAM,MAAM,UAAU,IAAI,YAAY,MAAM,MAAM,MAAM,UAAU;AAE1E,SAAO;AAAA,IACL,IAAI,MAAM,KAAK,mBAAmB,MAAM,GAAG,SAAS;AAAA,IACpD;AAAA;AAAA;AAAA,IAGA,mBAAmB,SAAS,WAAW,MAAM,OAAO;AAAA,IACpD,cAAc,KAAK,IAAI;AAAA,IACvB,YAAY,MAAM,KAAK;AAAA,IACvB,eAAe,gBAAgB,MAAM,KAAK,MAAM;AAAA,IAChD,MAAM,QAAQ,IAAI;AAAA,IAClB,MAAM;AAAA,EACR;AACF;AAEA,eAAsB,WACpB,QACA,SAEA,QACA,OAAyB,CAAC,GAC1B,eAAe,OACf;AACA,QAAM,MAA6B;AAAA,IACjC,eAAe;AAAA,IACf,QAAQ,OACL,OAAO,CAAC,UAAU,CAAC,eAAe,SAAS,MAAM,IAAI,CAAC,EACtD,IAAI,CAAC,UAAU,eAAe,OAAO,IAAI,CAAC;AAAA,EAC/C;AAEA,MAAI,IAAI,OAAO,WAAW,EAAG;AAE7B,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,QAAQ,OAAO,IAAI;AAAA,MACzD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,GAAG;AAAA,IAC1B,CAAC;AAED,QAAI,SAAS,GAAI;AACjB,UAAM,EAAE,OAAO,IAAI;AACnB,UAAM,UAAU,MAAM,SAAS,KAAK;AACpC,YAAQ,MAAM,6CAA6C,MAAM,WAAW,OAAO,EAAE;AAAA,EACvF,SAAS,OAAO;AACd,YAAQ,MAAM,oDAAoD,KAAK;AAAA,EACzE;AACF;","names":[]}
@@ -46,6 +46,7 @@ function Analytics({
46
46
  nonce,
47
47
  debugMode,
48
48
  metaPixelId,
49
+ openaiPixelId,
49
50
  redditPixelId,
50
51
  linkedInPartnerId,
51
52
  hotjarId,
@@ -127,6 +128,33 @@ function Analytics({
127
128
  }
128
129
  }
129
130
  ),
131
+ openaiPixelId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
132
+ "script",
133
+ {
134
+ async: true,
135
+ id: "openai-pixel",
136
+ dangerouslySetInnerHTML: {
137
+ __html: `
138
+ (function (w, d, s, u) {
139
+ if (w.oaiq) return;
140
+ var q = function () {
141
+ q.q.push(arguments);
142
+ };
143
+ q.q = [];
144
+ w.oaiq = q;
145
+ var js = d.createElement(s);
146
+ js.async = true;
147
+ js.src = u;
148
+ var f = d.getElementsByTagName(s)[0];
149
+ f.parentNode.insertBefore(js, f);
150
+ })(window, document, "script", "https://bzrcdn.openai.com/sdk/oaiq.min.js");
151
+
152
+ oaiq("init", { pixelId: "${openaiPixelId}" });
153
+ oaiq("measure", "page_viewed", { type: "contents" });
154
+ `
155
+ }
156
+ }
157
+ ),
130
158
  redditPixelId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
131
159
  "script",
132
160
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tanstack/index.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { type Metric, onCLS, onFCP, onINP, onLCP, onTTFB } from 'web-vitals';\nimport { useClickIdPersistence } from '../hooks/use-click-id-persistence';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\nfunction useReportWebVitals(reportWebVitalsFn: (metric: Metric) => void) {\n useEffect(() => {\n onCLS(reportWebVitalsFn);\n onLCP(reportWebVitalsFn);\n onINP(reportWebVitalsFn);\n onFCP(reportWebVitalsFn);\n onTTFB(reportWebVitalsFn);\n }, [reportWebVitalsFn]);\n}\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n redditPixelId,\n linkedInPartnerId,\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useClickIdPersistence();\n\n const { pathname } = useLocation();\n useWebAnalytics(pathname);\n useOutboundClickAnalytics();\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tanstack/index.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { type Metric, onCLS, onFCP, onINP, onLCP, onTTFB } from 'web-vitals';\nimport { useClickIdPersistence } from '../hooks/use-click-id-persistence';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\nfunction useReportWebVitals(reportWebVitalsFn: (metric: Metric) => void) {\n useEffect(() => {\n onCLS(reportWebVitalsFn);\n onLCP(reportWebVitalsFn);\n onINP(reportWebVitalsFn);\n onFCP(reportWebVitalsFn);\n onTTFB(reportWebVitalsFn);\n }, [reportWebVitalsFn]);\n}\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n openaiPixelId?: string;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n openaiPixelId,\n redditPixelId,\n linkedInPartnerId,\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useClickIdPersistence();\n\n const { pathname } = useLocation();\n useWebAnalytics(pathname);\n useOutboundClickAnalytics();\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {openaiPixelId && (\n <script\n async\n id=\"openai-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, s, u) {\n if (w.oaiq) return;\n var q = function () {\n q.q.push(arguments);\n };\n q.q = [];\n w.oaiq = q;\n var js = d.createElement(s);\n js.async = true;\n js.src = u;\n var f = d.getElementsByTagName(s)[0];\n f.parentNode.insertBefore(js, f);\n })(window, document, \"script\", \"https://bzrcdn.openai.com/sdk/oaiq.min.js\");\n\n oaiq(\"init\", { pixelId: \"${openaiPixelId}\" });\n oaiq(\"measure\", \"page_viewed\", { type: \"contents\" });\n `,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -9,6 +9,7 @@ interface Props {
9
9
  gaSrc?: string;
10
10
  gtmId?: GtmId;
11
11
  metaPixelId?: PixelId;
12
+ openaiPixelId?: string;
12
13
  redditPixelId?: PixelId$1;
13
14
  linkedInPartnerId?: `${number}`;
14
15
  hotjarId?: `${number}`;
@@ -17,6 +18,6 @@ interface Props {
17
18
  debugMode?: boolean;
18
19
  reportWebVitals?: boolean;
19
20
  }
20
- declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, redditPixelId, linkedInPartnerId, hotjarId, facebookAppId, reportWebVitals, }: Props): react_jsx_runtime.JSX.Element;
21
+ declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, hotjarId, facebookAppId, reportWebVitals, }: Props): react_jsx_runtime.JSX.Element;
21
22
 
22
23
  export { Analytics };
@@ -9,6 +9,7 @@ interface Props {
9
9
  gaSrc?: string;
10
10
  gtmId?: GtmId;
11
11
  metaPixelId?: PixelId;
12
+ openaiPixelId?: string;
12
13
  redditPixelId?: PixelId$1;
13
14
  linkedInPartnerId?: `${number}`;
14
15
  hotjarId?: `${number}`;
@@ -17,6 +18,6 @@ interface Props {
17
18
  debugMode?: boolean;
18
19
  reportWebVitals?: boolean;
19
20
  }
20
- declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, redditPixelId, linkedInPartnerId, hotjarId, facebookAppId, reportWebVitals, }: Props): react_jsx_runtime.JSX.Element;
21
+ declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, hotjarId, facebookAppId, reportWebVitals, }: Props): react_jsx_runtime.JSX.Element;
21
22
 
22
23
  export { Analytics };
@@ -22,6 +22,7 @@ function Analytics({
22
22
  nonce,
23
23
  debugMode,
24
24
  metaPixelId,
25
+ openaiPixelId,
25
26
  redditPixelId,
26
27
  linkedInPartnerId,
27
28
  hotjarId,
@@ -103,6 +104,33 @@ function Analytics({
103
104
  }
104
105
  }
105
106
  ),
107
+ openaiPixelId && /* @__PURE__ */ jsx(
108
+ "script",
109
+ {
110
+ async: true,
111
+ id: "openai-pixel",
112
+ dangerouslySetInnerHTML: {
113
+ __html: `
114
+ (function (w, d, s, u) {
115
+ if (w.oaiq) return;
116
+ var q = function () {
117
+ q.q.push(arguments);
118
+ };
119
+ q.q = [];
120
+ w.oaiq = q;
121
+ var js = d.createElement(s);
122
+ js.async = true;
123
+ js.src = u;
124
+ var f = d.getElementsByTagName(s)[0];
125
+ f.parentNode.insertBefore(js, f);
126
+ })(window, document, "script", "https://bzrcdn.openai.com/sdk/oaiq.min.js");
127
+
128
+ oaiq("init", { pixelId: "${openaiPixelId}" });
129
+ oaiq("measure", "page_viewed", { type: "contents" });
130
+ `
131
+ }
132
+ }
133
+ ),
106
134
  redditPixelId && /* @__PURE__ */ jsx(
107
135
  "script",
108
136
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tanstack/index.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { type Metric, onCLS, onFCP, onINP, onLCP, onTTFB } from 'web-vitals';\nimport { useClickIdPersistence } from '../hooks/use-click-id-persistence';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\nfunction useReportWebVitals(reportWebVitalsFn: (metric: Metric) => void) {\n useEffect(() => {\n onCLS(reportWebVitalsFn);\n onLCP(reportWebVitalsFn);\n onINP(reportWebVitalsFn);\n onFCP(reportWebVitalsFn);\n onTTFB(reportWebVitalsFn);\n }, [reportWebVitalsFn]);\n}\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n redditPixelId,\n linkedInPartnerId,\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useClickIdPersistence();\n\n const { pathname } = useLocation();\n useWebAnalytics(pathname);\n useOutboundClickAnalytics();\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tanstack/index.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { type Metric, onCLS, onFCP, onINP, onLCP, onTTFB } from 'web-vitals';\nimport { useClickIdPersistence } from '../hooks/use-click-id-persistence';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\nfunction useReportWebVitals(reportWebVitalsFn: (metric: Metric) => void) {\n useEffect(() => {\n onCLS(reportWebVitalsFn);\n onLCP(reportWebVitalsFn);\n onINP(reportWebVitalsFn);\n onFCP(reportWebVitalsFn);\n onTTFB(reportWebVitalsFn);\n }, [reportWebVitalsFn]);\n}\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n openaiPixelId?: string;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n openaiPixelId,\n redditPixelId,\n linkedInPartnerId,\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useClickIdPersistence();\n\n const { pathname } = useLocation();\n useWebAnalytics(pathname);\n useOutboundClickAnalytics();\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {openaiPixelId && (\n <script\n async\n id=\"openai-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, s, u) {\n if (w.oaiq) return;\n var q = function () {\n q.q.push(arguments);\n };\n q.q = [];\n w.oaiq = q;\n var js = d.createElement(s);\n js.async = true;\n js.src = u;\n var f = d.getElementsByTagName(s)[0];\n f.parentNode.insertBefore(js, f);\n })(window, document, \"script\", \"https://bzrcdn.openai.com/sdk/oaiq.min.js\");\n\n oaiq(\"init\", { pixelId: \"${openaiPixelId}\" });\n oaiq(\"measure\", \"page_viewed\", { type: \"contents\" });\n `,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport type { UpdateVisitorDTO } from '../visitor/types';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface Window extends Gtag {}\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, data, properties }: UpdateVisitorDTO) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (data) window.gtag('set', 'user_data', data);\n if (properties) window.gtag('set', 'user_properties', properties);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASO,SAAS,YACd,MACA,YACA;AACA,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,SAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEO,SAAS,UAAU,EAAE,SAAS,MAAM,WAAW,GAAqB;AACzE,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,MAAI,QAAS,QAAO,KAAK,OAAO,WAAW,OAAO;AAClD,MAAI,KAAM,QAAO,KAAK,OAAO,aAAa,IAAI;AAC9C,MAAI,WAAY,QAAO,KAAK,OAAO,mBAAmB,UAAU;AAClE;","names":[]}
1
+ {"version":3,"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport type { UpdateVisitorDTO } from '../visitor/types';\n\ndeclare global {\n // oxlint-disable-next-line typescript/no-empty-object-type\n interface Window extends Gtag {}\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, data, properties }: UpdateVisitorDTO) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (data) window.gtag('set', 'user_data', data);\n if (properties) window.gtag('set', 'user_properties', properties);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASO,SAAS,YACd,MACA,YACA;AACA,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,SAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEO,SAAS,UAAU,EAAE,SAAS,MAAM,WAAW,GAAqB;AACzE,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,MAAI,QAAS,QAAO,KAAK,OAAO,WAAW,OAAO;AAClD,MAAI,KAAM,QAAO,KAAK,OAAO,aAAa,IAAI;AAC9C,MAAI,WAAY,QAAO,KAAK,OAAO,mBAAmB,UAAU;AAClE;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport type { UpdateVisitorDTO } from '../visitor/types';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface Window extends Gtag {}\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, data, properties }: UpdateVisitorDTO) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (data) window.gtag('set', 'user_data', data);\n if (properties) window.gtag('set', 'user_properties', properties);\n}\n"],"mappings":";AASO,SAAS,YACd,MACA,YACA;AACA,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,SAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEO,SAAS,UAAU,EAAE,SAAS,MAAM,WAAW,GAAqB;AACzE,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,MAAI,QAAS,QAAO,KAAK,OAAO,WAAW,OAAO;AAClD,MAAI,KAAM,QAAO,KAAK,OAAO,aAAa,IAAI;AAC9C,MAAI,WAAY,QAAO,KAAK,OAAO,mBAAmB,UAAU;AAClE;","names":[]}
1
+ {"version":3,"sources":["../../src/third-parties/google-analytics.ts"],"sourcesContent":["import type { Gtag } from '../track/gtag';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport type { UpdateVisitorDTO } from '../visitor/types';\n\ndeclare global {\n // oxlint-disable-next-line typescript/no-empty-object-type\n interface Window extends Gtag {}\n}\n\nexport function sendGAEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>\n) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n window.gtag('event', name, properties);\n}\n\nexport function setGAUser({ user_id, data, properties }: UpdateVisitorDTO) {\n if (!window.gtag) {\n console.warn('GA has not been initialized');\n return;\n }\n if (user_id) window.gtag('set', 'user_id', user_id);\n if (data) window.gtag('set', 'user_data', data);\n if (properties) window.gtag('set', 'user_properties', properties);\n}\n"],"mappings":";AASO,SAAS,YACd,MACA,YACA;AACA,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,SAAO,KAAK,SAAS,MAAM,UAAU;AACvC;AAEO,SAAS,UAAU,EAAE,SAAS,MAAM,WAAW,GAAqB;AACzE,MAAI,CAAC,OAAO,MAAM;AAChB,YAAQ,KAAK,6BAA6B;AAC1C;AAAA,EACF;AACA,MAAI,QAAS,QAAO,KAAK,OAAO,WAAW,OAAO;AAClD,MAAI,KAAM,QAAO,KAAK,OAAO,aAAa,IAAI;AAC9C,MAAI,WAAY,QAAO,KAAK,OAAO,mBAAmB,UAAU;AAClE;","names":[]}