@snovasys/usage-analytics-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +638 -0
- package/dist/clarity.cjs +91 -0
- package/dist/clarity.cjs.map +1 -0
- package/dist/clarity.d.cts +19 -0
- package/dist/clarity.d.ts +19 -0
- package/dist/clarity.js +64 -0
- package/dist/clarity.js.map +1 -0
- package/dist/custom-api.cjs +98 -0
- package/dist/custom-api.cjs.map +1 -0
- package/dist/custom-api.d.cts +20 -0
- package/dist/custom-api.d.ts +20 -0
- package/dist/custom-api.js +71 -0
- package/dist/custom-api.js.map +1 -0
- package/dist/ga.cjs +96 -0
- package/dist/ga.cjs.map +1 -0
- package/dist/ga.d.cts +20 -0
- package/dist/ga.d.ts +20 -0
- package/dist/ga.js +69 -0
- package/dist/ga.js.map +1 -0
- package/dist/index.cjs +729 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +93 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +697 -0
- package/dist/index.js.map +1 -0
- package/dist/listener-CrNaKh1a.d.cts +58 -0
- package/dist/listener-CrNaKh1a.d.ts +58 -0
- package/dist/noop.cjs +43 -0
- package/dist/noop.cjs.map +1 -0
- package/dist/noop.d.cts +12 -0
- package/dist/noop.d.ts +12 -0
- package/dist/noop.js +15 -0
- package/dist/noop.js.map +1 -0
- package/dist/usage-analytics.min.js +2 -0
- package/dist/usage-analytics.min.js.map +1 -0
- package/package.json +59 -0
package/dist/clarity.cjs
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
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
|
+
// clarity.ts
|
|
21
|
+
var clarity_exports = {};
|
|
22
|
+
__export(clarity_exports, {
|
|
23
|
+
createClarityListener: () => createClarityListener
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(clarity_exports);
|
|
26
|
+
|
|
27
|
+
// src/listeners/clarity.ts
|
|
28
|
+
var CLARITY_SCRIPT_BASE = "https://www.clarity.ms/tag/";
|
|
29
|
+
function isBrowser() {
|
|
30
|
+
return typeof window !== "undefined";
|
|
31
|
+
}
|
|
32
|
+
function loadClarityScript(projectId) {
|
|
33
|
+
return new Promise((resolve) => {
|
|
34
|
+
if (!isBrowser()) {
|
|
35
|
+
resolve();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (typeof window.clarity === "function") {
|
|
39
|
+
resolve();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const script = document.createElement("script");
|
|
43
|
+
script.async = true;
|
|
44
|
+
script.src = `${CLARITY_SCRIPT_BASE}${encodeURIComponent(projectId)}`;
|
|
45
|
+
script.onload = () => resolve();
|
|
46
|
+
script.onerror = () => resolve();
|
|
47
|
+
document.head.appendChild(script);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function createClarityListener(config) {
|
|
51
|
+
const projectId = config.projectId;
|
|
52
|
+
let ready = false;
|
|
53
|
+
return {
|
|
54
|
+
async init(cfg) {
|
|
55
|
+
try {
|
|
56
|
+
const c = cfg ?? config;
|
|
57
|
+
const id = c.projectId;
|
|
58
|
+
if (!id || !isBrowser()) return;
|
|
59
|
+
await loadClarityScript(id);
|
|
60
|
+
ready = true;
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
track(envelope) {
|
|
65
|
+
try {
|
|
66
|
+
if (!isBrowser() || !ready || typeof window.clarity !== "function") return;
|
|
67
|
+
window.clarity("event", envelope.name);
|
|
68
|
+
if (envelope.properties && typeof window.clarity === "function") {
|
|
69
|
+
for (const [key, value] of Object.entries(envelope.properties)) {
|
|
70
|
+
if (typeof value === "string" || Array.isArray(value)) {
|
|
71
|
+
window.clarity("set", key, value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
identify(userId, _traits) {
|
|
79
|
+
try {
|
|
80
|
+
if (!isBrowser() || !ready || typeof window.clarity !== "function") return;
|
|
81
|
+
window.clarity("identify", userId, void 0, void 0, void 0);
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
88
|
+
0 && (module.exports = {
|
|
89
|
+
createClarityListener
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=clarity.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../clarity.ts","../src/listeners/clarity.ts"],"sourcesContent":["/**\n * Entry point: @snovasys/usage-analytics-sdk/clarity\n * Export Clarity listener factory for manual wiring or use via built-in registry (id: clarity).\n */\nexport { createClarityListener } from './src/listeners/clarity.js';\nexport type { ClarityListenerConfig } from './src/listeners/clarity.js';\nexport type { AnalyticsListener, EventEnvelope } from './src/types/index.js';\n","import type { AnalyticsListener } from '../types/listener.js';\nimport type { EventEnvelope } from '../types/envelope.js';\n\nexport interface ClarityListenerConfig {\n projectId: string;\n}\n\nconst CLARITY_SCRIPT_BASE = 'https://www.clarity.ms/tag/';\n\ndeclare global {\n interface Window {\n clarity?: (cmd: string, ...args: unknown[]) => void;\n }\n}\n\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction loadClarityScript(projectId: string): Promise<void> {\n return new Promise((resolve) => {\n if (!isBrowser()) {\n resolve();\n return;\n }\n if (typeof window.clarity === 'function') {\n resolve();\n return;\n }\n const script = document.createElement('script');\n script.async = true;\n script.src = `${CLARITY_SCRIPT_BASE}${encodeURIComponent(projectId)}`;\n script.onload = () => resolve();\n script.onerror = () => resolve();\n document.head.appendChild(script);\n });\n}\n\n/**\n * Listener that sends events to Microsoft Clarity via script injection.\n * Loads Clarity script with projectId; track → clarity(\"event\", name); identify → clarity(\"identify\", userId, ...).\n * No-op when typeof window === 'undefined' (SSR).\n */\nexport function createClarityListener(config: ClarityListenerConfig): AnalyticsListener {\n const projectId = config.projectId;\n let ready = false;\n\n return {\n async init(cfg: unknown): Promise<void> {\n try {\n const c = (cfg ?? config) as ClarityListenerConfig;\n const id = c.projectId;\n if (!id || !isBrowser()) return;\n await loadClarityScript(id);\n ready = true;\n } catch {\n // swallow\n }\n },\n track(envelope: EventEnvelope): void {\n try {\n if (!isBrowser() || !ready || typeof window.clarity !== 'function') return;\n window.clarity('event', envelope.name);\n if (envelope.properties && typeof window.clarity === 'function') {\n for (const [key, value] of Object.entries(envelope.properties)) {\n if (typeof value === 'string' || Array.isArray(value)) {\n window.clarity('set', key, value);\n }\n }\n }\n } catch {\n // swallow\n }\n },\n identify(userId: string, _traits?: Record<string, unknown>): void {\n try {\n if (!isBrowser() || !ready || typeof window.clarity !== 'function') return;\n window.clarity('identify', userId, undefined, undefined, undefined);\n } catch {\n // swallow\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,IAAM,sBAAsB;AAQ5B,SAAS,YAAqB;AAC5B,SAAO,OAAO,WAAW;AAC3B;AAEA,SAAS,kBAAkB,WAAkC;AAC3D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,CAAC,UAAU,GAAG;AAChB,cAAQ;AACR;AAAA,IACF;AACA,QAAI,OAAO,OAAO,YAAY,YAAY;AACxC,cAAQ;AACR;AAAA,IACF;AACA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,MAAM,GAAG,mBAAmB,GAAG,mBAAmB,SAAS,CAAC;AACnE,WAAO,SAAS,MAAM,QAAQ;AAC9B,WAAO,UAAU,MAAM,QAAQ;AAC/B,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AACH;AAOO,SAAS,sBAAsB,QAAkD;AACtF,QAAM,YAAY,OAAO;AACzB,MAAI,QAAQ;AAEZ,SAAO;AAAA,IACL,MAAM,KAAK,KAA6B;AACtC,UAAI;AACF,cAAM,IAAK,OAAO;AAClB,cAAM,KAAK,EAAE;AACb,YAAI,CAAC,MAAM,CAAC,UAAU,EAAG;AACzB,cAAM,kBAAkB,EAAE;AAC1B,gBAAQ;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,MAAM,UAA+B;AACnC,UAAI;AACF,YAAI,CAAC,UAAU,KAAK,CAAC,SAAS,OAAO,OAAO,YAAY,WAAY;AACpE,eAAO,QAAQ,SAAS,SAAS,IAAI;AACrC,YAAI,SAAS,cAAc,OAAO,OAAO,YAAY,YAAY;AAC/D,qBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,UAAU,GAAG;AAC9D,gBAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACrD,qBAAO,QAAQ,OAAO,KAAK,KAAK;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,SAAS,QAAgB,SAAyC;AAChE,UAAI;AACF,YAAI,CAAC,UAAU,KAAK,CAAC,SAAS,OAAO,OAAO,YAAY,WAAY;AACpE,eAAO,QAAQ,YAAY,QAAQ,QAAW,QAAW,MAAS;AAAA,MACpE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { A as AnalyticsListener } from './listener-CrNaKh1a.cjs';
|
|
2
|
+
export { E as EventEnvelope } from './listener-CrNaKh1a.cjs';
|
|
3
|
+
|
|
4
|
+
interface ClarityListenerConfig {
|
|
5
|
+
projectId: string;
|
|
6
|
+
}
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
clarity?: (cmd: string, ...args: unknown[]) => void;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Listener that sends events to Microsoft Clarity via script injection.
|
|
14
|
+
* Loads Clarity script with projectId; track → clarity("event", name); identify → clarity("identify", userId, ...).
|
|
15
|
+
* No-op when typeof window === 'undefined' (SSR).
|
|
16
|
+
*/
|
|
17
|
+
declare function createClarityListener(config: ClarityListenerConfig): AnalyticsListener;
|
|
18
|
+
|
|
19
|
+
export { AnalyticsListener, type ClarityListenerConfig, createClarityListener };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { A as AnalyticsListener } from './listener-CrNaKh1a.js';
|
|
2
|
+
export { E as EventEnvelope } from './listener-CrNaKh1a.js';
|
|
3
|
+
|
|
4
|
+
interface ClarityListenerConfig {
|
|
5
|
+
projectId: string;
|
|
6
|
+
}
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
clarity?: (cmd: string, ...args: unknown[]) => void;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Listener that sends events to Microsoft Clarity via script injection.
|
|
14
|
+
* Loads Clarity script with projectId; track → clarity("event", name); identify → clarity("identify", userId, ...).
|
|
15
|
+
* No-op when typeof window === 'undefined' (SSR).
|
|
16
|
+
*/
|
|
17
|
+
declare function createClarityListener(config: ClarityListenerConfig): AnalyticsListener;
|
|
18
|
+
|
|
19
|
+
export { AnalyticsListener, type ClarityListenerConfig, createClarityListener };
|
package/dist/clarity.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/listeners/clarity.ts
|
|
2
|
+
var CLARITY_SCRIPT_BASE = "https://www.clarity.ms/tag/";
|
|
3
|
+
function isBrowser() {
|
|
4
|
+
return typeof window !== "undefined";
|
|
5
|
+
}
|
|
6
|
+
function loadClarityScript(projectId) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
if (!isBrowser()) {
|
|
9
|
+
resolve();
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (typeof window.clarity === "function") {
|
|
13
|
+
resolve();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const script = document.createElement("script");
|
|
17
|
+
script.async = true;
|
|
18
|
+
script.src = `${CLARITY_SCRIPT_BASE}${encodeURIComponent(projectId)}`;
|
|
19
|
+
script.onload = () => resolve();
|
|
20
|
+
script.onerror = () => resolve();
|
|
21
|
+
document.head.appendChild(script);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function createClarityListener(config) {
|
|
25
|
+
const projectId = config.projectId;
|
|
26
|
+
let ready = false;
|
|
27
|
+
return {
|
|
28
|
+
async init(cfg) {
|
|
29
|
+
try {
|
|
30
|
+
const c = cfg ?? config;
|
|
31
|
+
const id = c.projectId;
|
|
32
|
+
if (!id || !isBrowser()) return;
|
|
33
|
+
await loadClarityScript(id);
|
|
34
|
+
ready = true;
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
track(envelope) {
|
|
39
|
+
try {
|
|
40
|
+
if (!isBrowser() || !ready || typeof window.clarity !== "function") return;
|
|
41
|
+
window.clarity("event", envelope.name);
|
|
42
|
+
if (envelope.properties && typeof window.clarity === "function") {
|
|
43
|
+
for (const [key, value] of Object.entries(envelope.properties)) {
|
|
44
|
+
if (typeof value === "string" || Array.isArray(value)) {
|
|
45
|
+
window.clarity("set", key, value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
identify(userId, _traits) {
|
|
53
|
+
try {
|
|
54
|
+
if (!isBrowser() || !ready || typeof window.clarity !== "function") return;
|
|
55
|
+
window.clarity("identify", userId, void 0, void 0, void 0);
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
createClarityListener
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=clarity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/listeners/clarity.ts"],"sourcesContent":["import type { AnalyticsListener } from '../types/listener.js';\nimport type { EventEnvelope } from '../types/envelope.js';\n\nexport interface ClarityListenerConfig {\n projectId: string;\n}\n\nconst CLARITY_SCRIPT_BASE = 'https://www.clarity.ms/tag/';\n\ndeclare global {\n interface Window {\n clarity?: (cmd: string, ...args: unknown[]) => void;\n }\n}\n\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction loadClarityScript(projectId: string): Promise<void> {\n return new Promise((resolve) => {\n if (!isBrowser()) {\n resolve();\n return;\n }\n if (typeof window.clarity === 'function') {\n resolve();\n return;\n }\n const script = document.createElement('script');\n script.async = true;\n script.src = `${CLARITY_SCRIPT_BASE}${encodeURIComponent(projectId)}`;\n script.onload = () => resolve();\n script.onerror = () => resolve();\n document.head.appendChild(script);\n });\n}\n\n/**\n * Listener that sends events to Microsoft Clarity via script injection.\n * Loads Clarity script with projectId; track → clarity(\"event\", name); identify → clarity(\"identify\", userId, ...).\n * No-op when typeof window === 'undefined' (SSR).\n */\nexport function createClarityListener(config: ClarityListenerConfig): AnalyticsListener {\n const projectId = config.projectId;\n let ready = false;\n\n return {\n async init(cfg: unknown): Promise<void> {\n try {\n const c = (cfg ?? config) as ClarityListenerConfig;\n const id = c.projectId;\n if (!id || !isBrowser()) return;\n await loadClarityScript(id);\n ready = true;\n } catch {\n // swallow\n }\n },\n track(envelope: EventEnvelope): void {\n try {\n if (!isBrowser() || !ready || typeof window.clarity !== 'function') return;\n window.clarity('event', envelope.name);\n if (envelope.properties && typeof window.clarity === 'function') {\n for (const [key, value] of Object.entries(envelope.properties)) {\n if (typeof value === 'string' || Array.isArray(value)) {\n window.clarity('set', key, value);\n }\n }\n }\n } catch {\n // swallow\n }\n },\n identify(userId: string, _traits?: Record<string, unknown>): void {\n try {\n if (!isBrowser() || !ready || typeof window.clarity !== 'function') return;\n window.clarity('identify', userId, undefined, undefined, undefined);\n } catch {\n // swallow\n }\n },\n };\n}\n"],"mappings":";AAOA,IAAM,sBAAsB;AAQ5B,SAAS,YAAqB;AAC5B,SAAO,OAAO,WAAW;AAC3B;AAEA,SAAS,kBAAkB,WAAkC;AAC3D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,CAAC,UAAU,GAAG;AAChB,cAAQ;AACR;AAAA,IACF;AACA,QAAI,OAAO,OAAO,YAAY,YAAY;AACxC,cAAQ;AACR;AAAA,IACF;AACA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,MAAM,GAAG,mBAAmB,GAAG,mBAAmB,SAAS,CAAC;AACnE,WAAO,SAAS,MAAM,QAAQ;AAC9B,WAAO,UAAU,MAAM,QAAQ;AAC/B,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AACH;AAOO,SAAS,sBAAsB,QAAkD;AACtF,QAAM,YAAY,OAAO;AACzB,MAAI,QAAQ;AAEZ,SAAO;AAAA,IACL,MAAM,KAAK,KAA6B;AACtC,UAAI;AACF,cAAM,IAAK,OAAO;AAClB,cAAM,KAAK,EAAE;AACb,YAAI,CAAC,MAAM,CAAC,UAAU,EAAG;AACzB,cAAM,kBAAkB,EAAE;AAC1B,gBAAQ;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,MAAM,UAA+B;AACnC,UAAI;AACF,YAAI,CAAC,UAAU,KAAK,CAAC,SAAS,OAAO,OAAO,YAAY,WAAY;AACpE,eAAO,QAAQ,SAAS,SAAS,IAAI;AACrC,YAAI,SAAS,cAAc,OAAO,OAAO,YAAY,YAAY;AAC/D,qBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,UAAU,GAAG;AAC9D,gBAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACrD,qBAAO,QAAQ,OAAO,KAAK,KAAK;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,SAAS,QAAgB,SAAyC;AAChE,UAAI;AACF,YAAI,CAAC,UAAU,KAAK,CAAC,SAAS,OAAO,OAAO,YAAY,WAAY;AACpE,eAAO,QAAQ,YAAY,QAAQ,QAAW,QAAW,MAAS;AAAA,MACpE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
// custom-api.ts
|
|
21
|
+
var custom_api_exports = {};
|
|
22
|
+
__export(custom_api_exports, {
|
|
23
|
+
createCustomApiListener: () => createCustomApiListener
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(custom_api_exports);
|
|
26
|
+
|
|
27
|
+
// src/listeners/custom-api.ts
|
|
28
|
+
var DEFAULT_BATCH_SIZE = 1;
|
|
29
|
+
var DEFAULT_FLUSH_INTERVAL_MS = 5e3;
|
|
30
|
+
function createCustomApiListener(config) {
|
|
31
|
+
const endpoint = config.endpoint;
|
|
32
|
+
const apiKey = config.apiKey;
|
|
33
|
+
const batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
34
|
+
const flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
35
|
+
let batch = [];
|
|
36
|
+
let flushTimer = null;
|
|
37
|
+
function scheduleFlush() {
|
|
38
|
+
if (flushTimer != null) return;
|
|
39
|
+
flushTimer = setTimeout(() => {
|
|
40
|
+
flushTimer = null;
|
|
41
|
+
sendBatch();
|
|
42
|
+
}, flushIntervalMs);
|
|
43
|
+
}
|
|
44
|
+
function sendBatch() {
|
|
45
|
+
if (batch.length === 0) return;
|
|
46
|
+
const toSend = [...batch];
|
|
47
|
+
batch = [];
|
|
48
|
+
const body = JSON.stringify(toSend.length === 1 ? toSend[0] : { events: toSend });
|
|
49
|
+
const headers = {
|
|
50
|
+
"Content-Type": "application/json"
|
|
51
|
+
};
|
|
52
|
+
if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
|
|
53
|
+
if (typeof fetch !== "undefined") {
|
|
54
|
+
fetch(endpoint, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers,
|
|
57
|
+
body,
|
|
58
|
+
keepalive: true
|
|
59
|
+
}).catch(() => {
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
init(_config) {
|
|
65
|
+
},
|
|
66
|
+
track(envelope) {
|
|
67
|
+
try {
|
|
68
|
+
batch.push(envelope);
|
|
69
|
+
if (batch.length >= batchSize) {
|
|
70
|
+
sendBatch();
|
|
71
|
+
} else if (flushIntervalMs > 0) {
|
|
72
|
+
scheduleFlush();
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
flush() {
|
|
78
|
+
if (flushTimer != null) {
|
|
79
|
+
clearTimeout(flushTimer);
|
|
80
|
+
flushTimer = null;
|
|
81
|
+
}
|
|
82
|
+
sendBatch();
|
|
83
|
+
return Promise.resolve();
|
|
84
|
+
},
|
|
85
|
+
teardown() {
|
|
86
|
+
if (flushTimer != null) {
|
|
87
|
+
clearTimeout(flushTimer);
|
|
88
|
+
flushTimer = null;
|
|
89
|
+
}
|
|
90
|
+
batch.length = 0;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
95
|
+
0 && (module.exports = {
|
|
96
|
+
createCustomApiListener
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=custom-api.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../custom-api.ts","../src/listeners/custom-api.ts"],"sourcesContent":["/**\n * Entry point: @snovasys/usage-analytics-sdk/custom-api\n * Export custom API listener factory for apps that send events to their backend.\n */\nexport { createCustomApiListener } from './src/listeners/custom-api.js';\nexport type { CustomApiListenerConfig } from './src/listeners/custom-api.js';\nexport type { AnalyticsListener, EventEnvelope } from './src/types/index.js';\n","import type { AnalyticsListener } from '../types/listener.js';\nimport type { EventEnvelope } from '../types/envelope.js';\n\nexport interface CustomApiListenerConfig {\n /** Endpoint URL for POST (e.g. https://api.example.com/analytics/events). */\n endpoint: string;\n /** Optional API key or bearer token. */\n apiKey?: string;\n /** Optional: batch size before sending. Default 1 (no batching). */\n batchSize?: number;\n /** Optional: max ms to wait before sending a partial batch. Default 5000. */\n flushIntervalMs?: number;\n}\n\nconst DEFAULT_BATCH_SIZE = 1;\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000;\n\n/**\n * Listener that POSTs events to a configurable endpoint.\n * Optional batching: accumulates events and sends when batchSize or flushIntervalMs is reached.\n */\nexport function createCustomApiListener(config: CustomApiListenerConfig): AnalyticsListener {\n const endpoint = config.endpoint;\n const apiKey = config.apiKey;\n const batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;\n const flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n\n let batch: EventEnvelope[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n function scheduleFlush(): void {\n if (flushTimer != null) return;\n flushTimer = setTimeout(() => {\n flushTimer = null;\n sendBatch();\n }, flushIntervalMs);\n }\n\n function sendBatch(): void {\n if (batch.length === 0) return;\n const toSend = [...batch];\n batch = [];\n const body = JSON.stringify(toSend.length === 1 ? toSend[0] : { events: toSend });\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;\n if (typeof fetch !== 'undefined') {\n fetch(endpoint, {\n method: 'POST',\n headers,\n body,\n keepalive: true,\n }).catch(() => {});\n }\n }\n\n return {\n init(_config: unknown): void {\n // config was passed at createCustomApiListener\n },\n track(envelope: EventEnvelope): void {\n try {\n batch.push(envelope);\n if (batch.length >= batchSize) {\n sendBatch();\n } else if (flushIntervalMs > 0) {\n scheduleFlush();\n }\n } catch {\n // swallow\n }\n },\n flush(): Promise<void> {\n if (flushTimer != null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n sendBatch();\n return Promise.resolve();\n },\n teardown(): void {\n if (flushTimer != null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n batch.length = 0;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACcA,IAAM,qBAAqB;AAC3B,IAAM,4BAA4B;AAM3B,SAAS,wBAAwB,QAAoD;AAC1F,QAAM,WAAW,OAAO;AACxB,QAAM,SAAS,OAAO;AACtB,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,kBAAkB,OAAO,mBAAmB;AAElD,MAAI,QAAyB,CAAC;AAC9B,MAAI,aAAmD;AAEvD,WAAS,gBAAsB;AAC7B,QAAI,cAAc,KAAM;AACxB,iBAAa,WAAW,MAAM;AAC5B,mBAAa;AACb,gBAAU;AAAA,IACZ,GAAG,eAAe;AAAA,EACpB;AAEA,WAAS,YAAkB;AACzB,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,SAAS,CAAC,GAAG,KAAK;AACxB,YAAQ,CAAC;AACT,UAAM,OAAO,KAAK,UAAU,OAAO,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,OAAO,CAAC;AAChF,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,IAClB;AACA,QAAI,OAAQ,SAAQ,eAAe,IAAI,UAAU,MAAM;AACvD,QAAI,OAAO,UAAU,aAAa;AAChC,YAAM,UAAU;AAAA,QACd,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,WAAW;AAAA,MACb,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,SAAwB;AAAA,IAE7B;AAAA,IACA,MAAM,UAA+B;AACnC,UAAI;AACF,cAAM,KAAK,QAAQ;AACnB,YAAI,MAAM,UAAU,WAAW;AAC7B,oBAAU;AAAA,QACZ,WAAW,kBAAkB,GAAG;AAC9B,wBAAc;AAAA,QAChB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,QAAuB;AACrB,UAAI,cAAc,MAAM;AACtB,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA,gBAAU;AACV,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAAA,IACA,WAAiB;AACf,UAAI,cAAc,MAAM;AACtB,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA,YAAM,SAAS;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { A as AnalyticsListener } from './listener-CrNaKh1a.cjs';
|
|
2
|
+
export { E as EventEnvelope } from './listener-CrNaKh1a.cjs';
|
|
3
|
+
|
|
4
|
+
interface CustomApiListenerConfig {
|
|
5
|
+
/** Endpoint URL for POST (e.g. https://api.example.com/analytics/events). */
|
|
6
|
+
endpoint: string;
|
|
7
|
+
/** Optional API key or bearer token. */
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/** Optional: batch size before sending. Default 1 (no batching). */
|
|
10
|
+
batchSize?: number;
|
|
11
|
+
/** Optional: max ms to wait before sending a partial batch. Default 5000. */
|
|
12
|
+
flushIntervalMs?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Listener that POSTs events to a configurable endpoint.
|
|
16
|
+
* Optional batching: accumulates events and sends when batchSize or flushIntervalMs is reached.
|
|
17
|
+
*/
|
|
18
|
+
declare function createCustomApiListener(config: CustomApiListenerConfig): AnalyticsListener;
|
|
19
|
+
|
|
20
|
+
export { AnalyticsListener, type CustomApiListenerConfig, createCustomApiListener };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { A as AnalyticsListener } from './listener-CrNaKh1a.js';
|
|
2
|
+
export { E as EventEnvelope } from './listener-CrNaKh1a.js';
|
|
3
|
+
|
|
4
|
+
interface CustomApiListenerConfig {
|
|
5
|
+
/** Endpoint URL for POST (e.g. https://api.example.com/analytics/events). */
|
|
6
|
+
endpoint: string;
|
|
7
|
+
/** Optional API key or bearer token. */
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/** Optional: batch size before sending. Default 1 (no batching). */
|
|
10
|
+
batchSize?: number;
|
|
11
|
+
/** Optional: max ms to wait before sending a partial batch. Default 5000. */
|
|
12
|
+
flushIntervalMs?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Listener that POSTs events to a configurable endpoint.
|
|
16
|
+
* Optional batching: accumulates events and sends when batchSize or flushIntervalMs is reached.
|
|
17
|
+
*/
|
|
18
|
+
declare function createCustomApiListener(config: CustomApiListenerConfig): AnalyticsListener;
|
|
19
|
+
|
|
20
|
+
export { AnalyticsListener, type CustomApiListenerConfig, createCustomApiListener };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/listeners/custom-api.ts
|
|
2
|
+
var DEFAULT_BATCH_SIZE = 1;
|
|
3
|
+
var DEFAULT_FLUSH_INTERVAL_MS = 5e3;
|
|
4
|
+
function createCustomApiListener(config) {
|
|
5
|
+
const endpoint = config.endpoint;
|
|
6
|
+
const apiKey = config.apiKey;
|
|
7
|
+
const batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
8
|
+
const flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
9
|
+
let batch = [];
|
|
10
|
+
let flushTimer = null;
|
|
11
|
+
function scheduleFlush() {
|
|
12
|
+
if (flushTimer != null) return;
|
|
13
|
+
flushTimer = setTimeout(() => {
|
|
14
|
+
flushTimer = null;
|
|
15
|
+
sendBatch();
|
|
16
|
+
}, flushIntervalMs);
|
|
17
|
+
}
|
|
18
|
+
function sendBatch() {
|
|
19
|
+
if (batch.length === 0) return;
|
|
20
|
+
const toSend = [...batch];
|
|
21
|
+
batch = [];
|
|
22
|
+
const body = JSON.stringify(toSend.length === 1 ? toSend[0] : { events: toSend });
|
|
23
|
+
const headers = {
|
|
24
|
+
"Content-Type": "application/json"
|
|
25
|
+
};
|
|
26
|
+
if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
|
|
27
|
+
if (typeof fetch !== "undefined") {
|
|
28
|
+
fetch(endpoint, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers,
|
|
31
|
+
body,
|
|
32
|
+
keepalive: true
|
|
33
|
+
}).catch(() => {
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
init(_config) {
|
|
39
|
+
},
|
|
40
|
+
track(envelope) {
|
|
41
|
+
try {
|
|
42
|
+
batch.push(envelope);
|
|
43
|
+
if (batch.length >= batchSize) {
|
|
44
|
+
sendBatch();
|
|
45
|
+
} else if (flushIntervalMs > 0) {
|
|
46
|
+
scheduleFlush();
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
flush() {
|
|
52
|
+
if (flushTimer != null) {
|
|
53
|
+
clearTimeout(flushTimer);
|
|
54
|
+
flushTimer = null;
|
|
55
|
+
}
|
|
56
|
+
sendBatch();
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
},
|
|
59
|
+
teardown() {
|
|
60
|
+
if (flushTimer != null) {
|
|
61
|
+
clearTimeout(flushTimer);
|
|
62
|
+
flushTimer = null;
|
|
63
|
+
}
|
|
64
|
+
batch.length = 0;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
createCustomApiListener
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=custom-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/listeners/custom-api.ts"],"sourcesContent":["import type { AnalyticsListener } from '../types/listener.js';\nimport type { EventEnvelope } from '../types/envelope.js';\n\nexport interface CustomApiListenerConfig {\n /** Endpoint URL for POST (e.g. https://api.example.com/analytics/events). */\n endpoint: string;\n /** Optional API key or bearer token. */\n apiKey?: string;\n /** Optional: batch size before sending. Default 1 (no batching). */\n batchSize?: number;\n /** Optional: max ms to wait before sending a partial batch. Default 5000. */\n flushIntervalMs?: number;\n}\n\nconst DEFAULT_BATCH_SIZE = 1;\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000;\n\n/**\n * Listener that POSTs events to a configurable endpoint.\n * Optional batching: accumulates events and sends when batchSize or flushIntervalMs is reached.\n */\nexport function createCustomApiListener(config: CustomApiListenerConfig): AnalyticsListener {\n const endpoint = config.endpoint;\n const apiKey = config.apiKey;\n const batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;\n const flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n\n let batch: EventEnvelope[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n function scheduleFlush(): void {\n if (flushTimer != null) return;\n flushTimer = setTimeout(() => {\n flushTimer = null;\n sendBatch();\n }, flushIntervalMs);\n }\n\n function sendBatch(): void {\n if (batch.length === 0) return;\n const toSend = [...batch];\n batch = [];\n const body = JSON.stringify(toSend.length === 1 ? toSend[0] : { events: toSend });\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;\n if (typeof fetch !== 'undefined') {\n fetch(endpoint, {\n method: 'POST',\n headers,\n body,\n keepalive: true,\n }).catch(() => {});\n }\n }\n\n return {\n init(_config: unknown): void {\n // config was passed at createCustomApiListener\n },\n track(envelope: EventEnvelope): void {\n try {\n batch.push(envelope);\n if (batch.length >= batchSize) {\n sendBatch();\n } else if (flushIntervalMs > 0) {\n scheduleFlush();\n }\n } catch {\n // swallow\n }\n },\n flush(): Promise<void> {\n if (flushTimer != null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n sendBatch();\n return Promise.resolve();\n },\n teardown(): void {\n if (flushTimer != null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n batch.length = 0;\n },\n };\n}\n"],"mappings":";AAcA,IAAM,qBAAqB;AAC3B,IAAM,4BAA4B;AAM3B,SAAS,wBAAwB,QAAoD;AAC1F,QAAM,WAAW,OAAO;AACxB,QAAM,SAAS,OAAO;AACtB,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,kBAAkB,OAAO,mBAAmB;AAElD,MAAI,QAAyB,CAAC;AAC9B,MAAI,aAAmD;AAEvD,WAAS,gBAAsB;AAC7B,QAAI,cAAc,KAAM;AACxB,iBAAa,WAAW,MAAM;AAC5B,mBAAa;AACb,gBAAU;AAAA,IACZ,GAAG,eAAe;AAAA,EACpB;AAEA,WAAS,YAAkB;AACzB,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,SAAS,CAAC,GAAG,KAAK;AACxB,YAAQ,CAAC;AACT,UAAM,OAAO,KAAK,UAAU,OAAO,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,OAAO,CAAC;AAChF,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,IAClB;AACA,QAAI,OAAQ,SAAQ,eAAe,IAAI,UAAU,MAAM;AACvD,QAAI,OAAO,UAAU,aAAa;AAChC,YAAM,UAAU;AAAA,QACd,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,WAAW;AAAA,MACb,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,SAAwB;AAAA,IAE7B;AAAA,IACA,MAAM,UAA+B;AACnC,UAAI;AACF,cAAM,KAAK,QAAQ;AACnB,YAAI,MAAM,UAAU,WAAW;AAC7B,oBAAU;AAAA,QACZ,WAAW,kBAAkB,GAAG;AAC9B,wBAAc;AAAA,QAChB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,QAAuB;AACrB,UAAI,cAAc,MAAM;AACtB,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA,gBAAU;AACV,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAAA,IACA,WAAiB;AACf,UAAI,cAAc,MAAM;AACtB,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA,YAAM,SAAS;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
|
package/dist/ga.cjs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
// ga.ts
|
|
21
|
+
var ga_exports = {};
|
|
22
|
+
__export(ga_exports, {
|
|
23
|
+
createGAListener: () => createGAListener
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(ga_exports);
|
|
26
|
+
|
|
27
|
+
// src/listeners/ga.ts
|
|
28
|
+
var GTAG_SCRIPT_URL = "https://www.googletagmanager.com/gtag/js";
|
|
29
|
+
function isBrowser() {
|
|
30
|
+
return typeof window !== "undefined";
|
|
31
|
+
}
|
|
32
|
+
function loadGtagScript(measurementId) {
|
|
33
|
+
return new Promise((resolve) => {
|
|
34
|
+
if (!isBrowser()) {
|
|
35
|
+
resolve();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (window.gtag) {
|
|
39
|
+
window.gtag("config", measurementId);
|
|
40
|
+
resolve();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
window.dataLayer = window.dataLayer ?? [];
|
|
44
|
+
const gtag = (...args) => {
|
|
45
|
+
window.dataLayer.push(args);
|
|
46
|
+
};
|
|
47
|
+
window.gtag = gtag;
|
|
48
|
+
gtag("js", /* @__PURE__ */ new Date());
|
|
49
|
+
const script = document.createElement("script");
|
|
50
|
+
script.async = true;
|
|
51
|
+
script.src = `${GTAG_SCRIPT_URL}?id=${encodeURIComponent(measurementId)}`;
|
|
52
|
+
script.onload = () => {
|
|
53
|
+
gtag("config", measurementId);
|
|
54
|
+
resolve();
|
|
55
|
+
};
|
|
56
|
+
script.onerror = () => resolve();
|
|
57
|
+
document.head.appendChild(script);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function createGAListener(config) {
|
|
61
|
+
const measurementId = config.measurementId;
|
|
62
|
+
let ready = false;
|
|
63
|
+
return {
|
|
64
|
+
async init(cfg) {
|
|
65
|
+
try {
|
|
66
|
+
const c = cfg ?? config;
|
|
67
|
+
const id = c.measurementId;
|
|
68
|
+
if (!id || !isBrowser()) return;
|
|
69
|
+
await loadGtagScript(id);
|
|
70
|
+
ready = true;
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
track(envelope) {
|
|
75
|
+
try {
|
|
76
|
+
if (!isBrowser() || !ready || typeof window.gtag !== "function") return;
|
|
77
|
+
const params = envelope.properties ?? {};
|
|
78
|
+
if (envelope.userId) params["user_id"] = envelope.userId;
|
|
79
|
+
window.gtag("event", envelope.name, params);
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
identify(userId, traits) {
|
|
84
|
+
try {
|
|
85
|
+
if (!isBrowser() || typeof window.gtag !== "function") return;
|
|
86
|
+
window.gtag("set", "user_properties", { user_id: userId, ...traits });
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
93
|
+
0 && (module.exports = {
|
|
94
|
+
createGAListener
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=ga.cjs.map
|
package/dist/ga.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../ga.ts","../src/listeners/ga.ts"],"sourcesContent":["/**\n * Entry point: @snovasys/usage-analytics-sdk/ga\n * Export GA listener factory for manual wiring or use via built-in registry (id: ga).\n */\nexport { createGAListener } from './src/listeners/ga.js';\nexport type { GAListenerConfig } from './src/listeners/ga.js';\nexport type { AnalyticsListener, EventEnvelope } from './src/types/index.js';\n","import type { AnalyticsListener } from '../types/listener.js';\nimport type { EventEnvelope } from '../types/envelope.js';\n\nexport interface GAListenerConfig {\n measurementId: string;\n}\n\nconst GTAG_SCRIPT_URL = 'https://www.googletagmanager.com/gtag/js';\n\ndeclare global {\n interface Window {\n dataLayer?: unknown[];\n gtag?: (...args: unknown[]) => void;\n }\n}\n\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction loadGtagScript(measurementId: string): Promise<void> {\n return new Promise((resolve) => {\n if (!isBrowser()) {\n resolve();\n return;\n }\n if (window.gtag) {\n window.gtag('config', measurementId);\n resolve();\n return;\n }\n window.dataLayer = window.dataLayer ?? [];\n const gtag = (...args: unknown[]) => {\n window.dataLayer!.push(args);\n };\n window.gtag = gtag;\n gtag('js', new Date());\n const script = document.createElement('script');\n script.async = true;\n script.src = `${GTAG_SCRIPT_URL}?id=${encodeURIComponent(measurementId)}`;\n script.onload = () => {\n gtag('config', measurementId);\n resolve();\n };\n script.onerror = () => resolve();\n document.head.appendChild(script);\n });\n}\n\n/**\n * Listener that sends events to Google Analytics 4 via gtag.\n * Loads gtag script with measurementId; track → gtag('event', name, properties).\n * No-op when typeof window === 'undefined' (SSR).\n */\nexport function createGAListener(config: GAListenerConfig): AnalyticsListener {\n const measurementId = config.measurementId;\n let ready = false;\n\n return {\n async init(cfg: unknown): Promise<void> {\n try {\n const c = (cfg ?? config) as GAListenerConfig;\n const id = c.measurementId;\n if (!id || !isBrowser()) return;\n await loadGtagScript(id);\n ready = true;\n } catch {\n // swallow\n }\n },\n track(envelope: EventEnvelope): void {\n try {\n if (!isBrowser() || !ready || typeof window.gtag !== 'function') return;\n const params = envelope.properties ?? {};\n if (envelope.userId) (params as Record<string, unknown>)['user_id'] = envelope.userId;\n window.gtag('event', envelope.name, params);\n } catch {\n // swallow\n }\n },\n identify(userId: string, traits?: Record<string, unknown>): void {\n try {\n if (!isBrowser() || typeof window.gtag !== 'function') return;\n window.gtag('set', 'user_properties', { user_id: userId, ...traits });\n } catch {\n // swallow\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,IAAM,kBAAkB;AASxB,SAAS,YAAqB;AAC5B,SAAO,OAAO,WAAW;AAC3B;AAEA,SAAS,eAAe,eAAsC;AAC5D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,CAAC,UAAU,GAAG;AAChB,cAAQ;AACR;AAAA,IACF;AACA,QAAI,OAAO,MAAM;AACf,aAAO,KAAK,UAAU,aAAa;AACnC,cAAQ;AACR;AAAA,IACF;AACA,WAAO,YAAY,OAAO,aAAa,CAAC;AACxC,UAAM,OAAO,IAAI,SAAoB;AACnC,aAAO,UAAW,KAAK,IAAI;AAAA,IAC7B;AACA,WAAO,OAAO;AACd,SAAK,MAAM,oBAAI,KAAK,CAAC;AACrB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,MAAM,GAAG,eAAe,OAAO,mBAAmB,aAAa,CAAC;AACvE,WAAO,SAAS,MAAM;AACpB,WAAK,UAAU,aAAa;AAC5B,cAAQ;AAAA,IACV;AACA,WAAO,UAAU,MAAM,QAAQ;AAC/B,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AACH;AAOO,SAAS,iBAAiB,QAA6C;AAC5E,QAAM,gBAAgB,OAAO;AAC7B,MAAI,QAAQ;AAEZ,SAAO;AAAA,IACL,MAAM,KAAK,KAA6B;AACtC,UAAI;AACF,cAAM,IAAK,OAAO;AAClB,cAAM,KAAK,EAAE;AACb,YAAI,CAAC,MAAM,CAAC,UAAU,EAAG;AACzB,cAAM,eAAe,EAAE;AACvB,gBAAQ;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,MAAM,UAA+B;AACnC,UAAI;AACF,YAAI,CAAC,UAAU,KAAK,CAAC,SAAS,OAAO,OAAO,SAAS,WAAY;AACjE,cAAM,SAAS,SAAS,cAAc,CAAC;AACvC,YAAI,SAAS,OAAQ,CAAC,OAAmC,SAAS,IAAI,SAAS;AAC/E,eAAO,KAAK,SAAS,SAAS,MAAM,MAAM;AAAA,MAC5C,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,SAAS,QAAgB,QAAwC;AAC/D,UAAI;AACF,YAAI,CAAC,UAAU,KAAK,OAAO,OAAO,SAAS,WAAY;AACvD,eAAO,KAAK,OAAO,mBAAmB,EAAE,SAAS,QAAQ,GAAG,OAAO,CAAC;AAAA,MACtE,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/ga.d.cts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { A as AnalyticsListener } from './listener-CrNaKh1a.cjs';
|
|
2
|
+
export { E as EventEnvelope } from './listener-CrNaKh1a.cjs';
|
|
3
|
+
|
|
4
|
+
interface GAListenerConfig {
|
|
5
|
+
measurementId: string;
|
|
6
|
+
}
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
dataLayer?: unknown[];
|
|
10
|
+
gtag?: (...args: unknown[]) => void;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Listener that sends events to Google Analytics 4 via gtag.
|
|
15
|
+
* Loads gtag script with measurementId; track → gtag('event', name, properties).
|
|
16
|
+
* No-op when typeof window === 'undefined' (SSR).
|
|
17
|
+
*/
|
|
18
|
+
declare function createGAListener(config: GAListenerConfig): AnalyticsListener;
|
|
19
|
+
|
|
20
|
+
export { AnalyticsListener, type GAListenerConfig, createGAListener };
|
package/dist/ga.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { A as AnalyticsListener } from './listener-CrNaKh1a.js';
|
|
2
|
+
export { E as EventEnvelope } from './listener-CrNaKh1a.js';
|
|
3
|
+
|
|
4
|
+
interface GAListenerConfig {
|
|
5
|
+
measurementId: string;
|
|
6
|
+
}
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
dataLayer?: unknown[];
|
|
10
|
+
gtag?: (...args: unknown[]) => void;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Listener that sends events to Google Analytics 4 via gtag.
|
|
15
|
+
* Loads gtag script with measurementId; track → gtag('event', name, properties).
|
|
16
|
+
* No-op when typeof window === 'undefined' (SSR).
|
|
17
|
+
*/
|
|
18
|
+
declare function createGAListener(config: GAListenerConfig): AnalyticsListener;
|
|
19
|
+
|
|
20
|
+
export { AnalyticsListener, type GAListenerConfig, createGAListener };
|