onerway-analytics 1.0.3 → 1.2.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.
@@ -24,7 +24,7 @@ var OnrwayAnalytics = (() => {
24
24
  API_KEY_MAP: () => API_KEY_MAP,
25
25
  Analytics: () => Analytics,
26
26
  DEFAULT_CONFIG: () => DEFAULT_CONFIG,
27
- GAManager: () => GAManager,
27
+ GTMManager: () => GTMManager,
28
28
  SDK_VERSION: () => SDK_VERSION,
29
29
  STORAGE_KEYS: () => STORAGE_KEYS,
30
30
  Sender: () => Sender,
@@ -644,34 +644,41 @@ var OnrwayAnalytics = (() => {
644
644
  });
645
645
  }
646
646
 
647
- // src/core/ga-loader.ts
648
- function loadGtagScript(measurementId) {
649
- return new Promise((resolve, reject) => {
650
- if (document.querySelector(`script[src*="googletagmanager.com/gtag/js"]`)) {
651
- resolve();
652
- return;
653
- }
647
+ // src/core/gtm-loader.ts
648
+ function initGTM(config) {
649
+ if (!config.enabled || !config.containerId) return;
650
+ if (typeof window === "undefined") return;
651
+ const dataLayerName = config.dataLayerName || "dataLayer";
652
+ const w2 = window;
653
+ if (!Array.isArray(w2[dataLayerName])) {
654
+ w2[dataLayerName] = [];
655
+ }
656
+ w2[dataLayerName].push({ "gtm.start": (/* @__PURE__ */ new Date()).getTime(), event: "gtm.js" });
657
+ const existingScript = document.querySelector(
658
+ `script[src*="googletagmanager.com/gtm.js?id=${config.containerId}"]`
659
+ );
660
+ if (!existingScript) {
661
+ const dl = dataLayerName !== "dataLayer" ? `&l=${encodeURIComponent(dataLayerName)}` : "";
654
662
  const script = document.createElement("script");
655
663
  script.async = true;
656
- script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
657
- script.onload = () => resolve();
658
- script.onerror = () => reject(new Error("Failed to load gtag.js"));
659
- document.head.appendChild(script);
660
- });
661
- }
662
- async function initGA(config) {
663
- if (!config.enabled || !config.measurementId) return;
664
- if (typeof window === "undefined") return;
665
- window.dataLayer = window.dataLayer || [];
666
- window.gtag = function gtag() {
667
- window.dataLayer.push(arguments);
668
- };
669
- window.gtag("js", /* @__PURE__ */ new Date());
670
- window.gtag("config", config.measurementId, {
671
- send_page_view: config.sendPageView ?? false,
672
- debug_mode: config.debugMode ?? false
673
- });
674
- await loadGtagScript(config.measurementId);
664
+ script.src = `https://www.googletagmanager.com/gtm.js?id=${config.containerId}${dl}`;
665
+ const firstScript = document.getElementsByTagName("script")[0];
666
+ firstScript.parentNode?.insertBefore(script, firstScript);
667
+ }
668
+ if (!document.querySelector(`noscript[data-gtm-id="${config.containerId}"]`)) {
669
+ const noscript = document.createElement("noscript");
670
+ noscript.setAttribute("data-gtm-id", config.containerId);
671
+ const iframe = document.createElement("iframe");
672
+ iframe.src = `https://www.googletagmanager.com/ns.html?id=${config.containerId}`;
673
+ iframe.height = "0";
674
+ iframe.width = "0";
675
+ iframe.style.display = "none";
676
+ iframe.style.visibility = "hidden";
677
+ noscript.appendChild(iframe);
678
+ if (document.body) {
679
+ document.body.insertBefore(noscript, document.body.firstChild);
680
+ }
681
+ }
675
682
  }
676
683
 
677
684
  // node_modules/web-vitals/dist/web-vitals.js
@@ -950,126 +957,43 @@ var OnrwayAnalytics = (() => {
950
957
  }
951
958
  }
952
959
 
953
- // src/core/ga-adapter.ts
954
- var GA4_RESERVED_NAMES = /* @__PURE__ */ new Set([
955
- "ad_activeview",
956
- "ad_click",
957
- "ad_exposure",
958
- "ad_impression",
959
- "ad_query",
960
- "adunit_exposure",
961
- "app_clear_data",
962
- "app_exception",
963
- "app_install",
964
- "app_remove",
965
- "app_update",
966
- "app_upgrade",
967
- "error",
968
- "firebase_campaign",
969
- "first_open",
970
- "first_visit",
971
- "in_app_purchase",
972
- "notification_dismiss",
973
- "notification_foreground",
974
- "notification_open",
975
- "notification_receive",
976
- "os_update",
977
- "session_start",
978
- "user_engagement"
979
- ]);
980
- var SYSTEM_EVENTS = /* @__PURE__ */ new Set(["web_vital", "error_event"]);
981
- function sanitizeEventName(name) {
982
- let result = name.replace(/[^a-zA-Z0-9_]/g, "_");
983
- if (!/^[a-zA-Z]/.test(result)) result = "e_" + result;
984
- return result.slice(0, 40);
985
- }
986
- function trackToGA(eventName, properties, options) {
987
- if (typeof window === "undefined" || !window.gtag) return;
988
- const safeName = GA4_RESERVED_NAMES.has(eventName) ? `custom_${eventName}`.slice(0, 40) : sanitizeEventName(eventName);
989
- const params = { ...properties };
990
- params.session_id = options.sessionId;
991
- params.page_location = options.pageUrl;
992
- params.page_referrer = options.referrer;
993
- if (!SYSTEM_EVENTS.has(eventName)) {
994
- params.engagement_time_msec = 100;
995
- }
996
- window.gtag("event", safeName, params);
997
- }
998
- function setGAUserId(userId) {
999
- if (typeof window === "undefined" || !window.gtag) return;
1000
- window.gtag("set", { user_id: userId ?? void 0 });
1001
- }
1002
- function setGAUserProperties(properties) {
1003
- if (typeof window === "undefined" || !window.gtag) return;
1004
- window.gtag("set", "user_properties", properties);
1005
- }
1006
- function setGAMarketing(marketing) {
1007
- if (typeof window === "undefined" || !window.gtag) return;
1008
- const params = {};
1009
- if (marketing.utm_source) params.utm_source = marketing.utm_source;
1010
- if (marketing.utm_medium) params.utm_medium = marketing.utm_medium;
1011
- if (marketing.utm_campaign) params.utm_campaign = marketing.utm_campaign;
1012
- if (marketing.utm_term) params.utm_term = marketing.utm_term;
1013
- if (marketing.utm_content) params.utm_content = marketing.utm_content;
1014
- if (Object.keys(params).length > 0) {
1015
- window.gtag("set", params);
1016
- }
1017
- }
1018
-
1019
- // src/core/ga-manager.ts
1020
- var GAManager = class {
960
+ // src/core/gtm-manager.ts
961
+ var GTMManager = class {
1021
962
  constructor() {
1022
963
  this._initialized = false;
964
+ this._dataLayerName = "dataLayer";
1023
965
  }
1024
966
  get ready() {
1025
- return this._initialized && typeof window !== "undefined" && typeof window.gtag === "function";
1026
- }
1027
- get measurementId() {
1028
- return this._measurementId;
1029
- }
1030
- track(eventName, properties) {
1031
- if (!this.ready) return;
1032
- window.gtag("event", eventName, properties ?? {});
1033
- }
1034
- setUserId(userId) {
1035
- if (!this.ready) return;
1036
- window.gtag("set", { user_id: userId ?? void 0 });
967
+ return this._initialized && typeof window !== "undefined";
1037
968
  }
1038
- setUserProperties(properties) {
1039
- if (!this.ready) return;
1040
- window.gtag("set", "user_properties", properties);
969
+ get containerId() {
970
+ return this._containerId;
1041
971
  }
1042
- set(keyOrParams, value) {
972
+ push(data) {
1043
973
  if (!this.ready) return;
1044
- if (typeof keyOrParams === "string") {
1045
- window.gtag("set", keyOrParams, value);
1046
- } else {
1047
- window.gtag("set", keyOrParams);
974
+ const w2 = window;
975
+ const dl = w2[this._dataLayerName];
976
+ if (Array.isArray(dl)) {
977
+ dl.push(data);
1048
978
  }
1049
979
  }
1050
- config(params) {
1051
- if (!this.ready || !this._measurementId) return;
1052
- window.gtag("config", this._measurementId, params ?? {});
1053
- }
1054
- consent(mode, params) {
1055
- if (!this.ready) return;
1056
- window.gtag("consent", mode, params);
980
+ track(eventName, properties) {
981
+ this.push({ event: eventName, ...properties || {} });
1057
982
  }
1058
- get(key, callback) {
1059
- if (!this.ready || !this._measurementId) return;
1060
- window.gtag("get", this._measurementId, key, callback);
983
+ setUserId(userId) {
984
+ this.push({ userId: userId ?? void 0 });
1061
985
  }
1062
- gtag(...args) {
1063
- if (typeof window === "undefined" || !window.gtag) return;
1064
- window.gtag(...args);
986
+ setUserProperties(properties) {
987
+ this.push(properties);
1065
988
  }
1066
- _init(measurementId) {
1067
- this._measurementId = measurementId;
989
+ _init(containerId, dataLayerName = "dataLayer") {
990
+ this._containerId = containerId;
991
+ this._dataLayerName = dataLayerName;
1068
992
  this._initialized = true;
1069
993
  }
1070
994
  _destroy() {
1071
995
  this._initialized = false;
1072
- this._measurementId = void 0;
996
+ this._containerId = void 0;
1073
997
  }
1074
998
  };
1075
999
 
@@ -1083,11 +1007,8 @@ var OnrwayAnalytics = (() => {
1083
1007
  this.userProps = {};
1084
1008
  this.initialized = false;
1085
1009
  this.retrying = 0;
1086
- this.gaInitialized = false;
1087
- this.gaPendingQueue = [];
1088
- this.gaPendingIdentify = null;
1089
1010
  this.unloadHandler = null;
1090
- this.ga = new GAManager();
1011
+ this.gtm = new GTMManager();
1091
1012
  this.config = {
1092
1013
  debug: false,
1093
1014
  autoTrack: true,
@@ -1103,6 +1024,7 @@ var OnrwayAnalytics = (() => {
1103
1024
  this.clientType = DEFAULT_CONFIG.clientType;
1104
1025
  this.batchPageId = this.generateBatchPageId();
1105
1026
  this.sessionManager = new SessionManager(this.config.sessionTimeout);
1027
+ this.sampled = this.resolveSampling();
1106
1028
  if (isBrowser()) {
1107
1029
  this.recoverFailedEvents();
1108
1030
  }
@@ -1116,29 +1038,10 @@ var OnrwayAnalytics = (() => {
1116
1038
  if (isBrowser() && this.config.performance?.enabled !== false) {
1117
1039
  initPerformanceMonitor(this, this.config.performance);
1118
1040
  }
1119
- if (isBrowser() && this.config.ga?.enabled) {
1120
- this.ga._init(this.config.ga.measurementId);
1121
- initGA(this.config.ga).then(() => {
1122
- this.gaInitialized = true;
1123
- this.log("GA4 initialized with measurementId:", this.config.ga?.measurementId);
1124
- setGAMarketing(collectMarketing());
1125
- if (this.gaPendingIdentify) {
1126
- setGAUserId(this.gaPendingIdentify.userId);
1127
- if (this.gaPendingIdentify.attributes) {
1128
- setGAUserProperties(this.gaPendingIdentify.attributes);
1129
- }
1130
- this.gaPendingIdentify = null;
1131
- }
1132
- for (const { eventName, properties, options } of this.gaPendingQueue) {
1133
- trackToGA(eventName, properties, options);
1134
- }
1135
- this.gaPendingQueue = [];
1136
- }).catch((error) => {
1137
- this.ga._destroy();
1138
- this.gaPendingIdentify = null;
1139
- this.gaPendingQueue = [];
1140
- this.log("Failed to initialize GA4:", error);
1141
- });
1041
+ if (isBrowser() && this.config.gtm?.enabled) {
1042
+ initGTM(this.config.gtm);
1043
+ this.gtm._init(this.config.gtm.containerId, this.config.gtm.dataLayerName);
1044
+ this.log("GTM initialized with containerId:", this.config.gtm.containerId);
1142
1045
  }
1143
1046
  this.initialized = true;
1144
1047
  this.log("Analytics SDK initialized", {
@@ -1155,19 +1058,16 @@ var OnrwayAnalytics = (() => {
1155
1058
  this.log("Invalid event name");
1156
1059
  return;
1157
1060
  }
1061
+ if (!this.sampled) return;
1158
1062
  const normalizedProps = properties && isObject(properties) ? properties : {};
1159
1063
  const isKeyEvent = options?.keyEvent === true || this.isKeyEvent(eventName);
1160
- if (this.config.ga?.enabled) {
1161
- const gaOptions = {
1162
- sessionId: this.sessionManager.getSessionId(),
1163
- pageUrl: isBrowser() ? getPageUrl() : "",
1064
+ if (this.gtm.ready) {
1065
+ this.gtm.track(eventName, {
1066
+ ...normalizedProps,
1067
+ session_id: this.sessionManager.getSessionId(),
1068
+ page_url: isBrowser() ? getPageUrl() : "",
1164
1069
  referrer: isBrowser() ? document.referrer : ""
1165
- };
1166
- if (this.gaInitialized) {
1167
- trackToGA(eventName, normalizedProps, gaOptions);
1168
- } else {
1169
- this.gaPendingQueue.push({ eventName, properties: normalizedProps, options: gaOptions });
1170
- }
1070
+ });
1171
1071
  }
1172
1072
  if (this.config.disableServer) return;
1173
1073
  const event = {
@@ -1196,13 +1096,11 @@ var OnrwayAnalytics = (() => {
1196
1096
  if (attributes && isObject(attributes)) {
1197
1097
  this.userProps = attributes;
1198
1098
  }
1199
- if (this.gaInitialized) {
1200
- setGAUserId(userId);
1099
+ if (this.gtm.ready) {
1100
+ this.gtm.setUserId(userId);
1201
1101
  if (attributes && isObject(attributes)) {
1202
- setGAUserProperties(attributes);
1102
+ this.gtm.setUserProperties(attributes);
1203
1103
  }
1204
- } else if (this.config.ga?.enabled) {
1205
- this.gaPendingIdentify = { userId, attributes };
1206
1104
  }
1207
1105
  this.log("User identified:", { userId, attributes });
1208
1106
  if (wasAnonymous && this.buffer.length > 0) {
@@ -1223,8 +1121,8 @@ var OnrwayAnalytics = (() => {
1223
1121
  clearTimeout(this.bufferTimer);
1224
1122
  this.bufferTimer = null;
1225
1123
  }
1226
- if (this.gaInitialized) {
1227
- setGAUserId(null);
1124
+ if (this.gtm.ready) {
1125
+ this.gtm.setUserId(null);
1228
1126
  }
1229
1127
  this.log("Analytics reset");
1230
1128
  }
@@ -1249,6 +1147,14 @@ var OnrwayAnalytics = (() => {
1249
1147
  console.log("[Analytics]", ...args);
1250
1148
  }
1251
1149
  }
1150
+ resolveSampling() {
1151
+ const rate = this.config.sampleRate ?? 1;
1152
+ if (rate >= 1) return true;
1153
+ if (rate <= 0) return false;
1154
+ const decision = Math.random() < rate;
1155
+ this.log(`Sampling decision: ${decision ? "included" : "excluded"} (sampleRate=${rate})`);
1156
+ return decision;
1157
+ }
1252
1158
  getOrCreateClientId() {
1253
1159
  if (!isBrowser()) return generateUUID();
1254
1160
  let clientId = safeLocalStorageGet(STORAGE_KEYS.CLIENT_ID);
@@ -1377,6 +1283,7 @@ var OnrwayAnalytics = (() => {
1377
1283
  }
1378
1284
  recoverFailedEvents() {
1379
1285
  if (this.config.disableServer) return;
1286
+ if (!this.sampled) return;
1380
1287
  const failedEvents = StorageQueue.recover();
1381
1288
  if (failedEvents.length > 0) {
1382
1289
  this.log(`Recovered ${failedEvents.length} failed events from storage`);