@callforge/tracking-client 0.2.0 → 0.3.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/dist/index.d.mts CHANGED
@@ -77,6 +77,10 @@ declare class CallForge {
77
77
  private readonly cache;
78
78
  private sessionPromise;
79
79
  private customParams;
80
+ private ga4PollInterval;
81
+ private ga4PollTimeout;
82
+ private sessionId;
83
+ private sessionCreated;
80
84
  private constructor();
81
85
  /**
82
86
  * Initialize the CallForge tracking client.
@@ -94,9 +98,22 @@ declare class CallForge {
94
98
  onReady(callback: ReadyCallback): void;
95
99
  /**
96
100
  * Set custom tracking parameters.
97
- * Merges with existing params (new values override).
101
+ * If session already exists, sends PATCH to update.
102
+ * Otherwise queues params for next session request.
98
103
  */
99
- setParams(params: Record<string, string>): void;
104
+ setParams(params: Record<string, string>): Promise<void>;
105
+ /**
106
+ * Get the currently queued custom params.
107
+ */
108
+ getQueuedParams(): TrackingParams;
109
+ private patchSession;
110
+ /**
111
+ * Start polling for the GA4 _ga cookie.
112
+ * If found immediately, calls setParams right away.
113
+ * Otherwise polls every 500ms for up to 10 seconds.
114
+ */
115
+ startGA4CookiePolling(): void;
116
+ private stopGA4CookiePolling;
100
117
  private fetchSession;
101
118
  private getLocationId;
102
119
  private getAutoParams;
package/dist/index.d.ts CHANGED
@@ -77,6 +77,10 @@ declare class CallForge {
77
77
  private readonly cache;
78
78
  private sessionPromise;
79
79
  private customParams;
80
+ private ga4PollInterval;
81
+ private ga4PollTimeout;
82
+ private sessionId;
83
+ private sessionCreated;
80
84
  private constructor();
81
85
  /**
82
86
  * Initialize the CallForge tracking client.
@@ -94,9 +98,22 @@ declare class CallForge {
94
98
  onReady(callback: ReadyCallback): void;
95
99
  /**
96
100
  * Set custom tracking parameters.
97
- * Merges with existing params (new values override).
101
+ * If session already exists, sends PATCH to update.
102
+ * Otherwise queues params for next session request.
98
103
  */
99
- setParams(params: Record<string, string>): void;
104
+ setParams(params: Record<string, string>): Promise<void>;
105
+ /**
106
+ * Get the currently queued custom params.
107
+ */
108
+ getQueuedParams(): TrackingParams;
109
+ private patchSession;
110
+ /**
111
+ * Start polling for the GA4 _ga cookie.
112
+ * If found immediately, calls setParams right away.
113
+ * Otherwise polls every 500ms for up to 10 seconds.
114
+ */
115
+ startGA4CookiePolling(): void;
116
+ private stopGA4CookiePolling;
100
117
  private fetchSession;
101
118
  private getLocationId;
102
119
  private getAutoParams;
package/dist/index.js CHANGED
@@ -129,17 +129,27 @@ var TrackingCache = class {
129
129
 
130
130
  // src/client.ts
131
131
  var DEFAULT_ENDPOINT = "https://tracking.callforge.io";
132
+ function getGA4ClientId() {
133
+ if (typeof document === "undefined") return null;
134
+ const match = document.cookie.match(/_ga=GA\d+\.\d+\.(.+?)(?:;|$)/);
135
+ return match ? match[1] : null;
136
+ }
132
137
  var FETCH_TIMEOUT_MS = 1e4;
133
138
  var AUTO_PARAMS = ["gclid", "gbraid", "wbraid", "msclkid", "fbclid"];
134
139
  var CallForge = class _CallForge {
135
140
  constructor(config) {
136
141
  this.sessionPromise = null;
137
142
  this.customParams = {};
143
+ this.ga4PollInterval = null;
144
+ this.ga4PollTimeout = null;
145
+ this.sessionId = null;
146
+ this.sessionCreated = false;
138
147
  this.config = {
139
148
  categoryId: config.categoryId,
140
149
  endpoint: config.endpoint || DEFAULT_ENDPOINT
141
150
  };
142
151
  this.cache = new TrackingCache(config.categoryId);
152
+ this.startGA4CookiePolling();
143
153
  }
144
154
  /**
145
155
  * Initialize the CallForge tracking client.
@@ -168,16 +178,80 @@ var CallForge = class _CallForge {
168
178
  }
169
179
  /**
170
180
  * Set custom tracking parameters.
171
- * Merges with existing params (new values override).
181
+ * If session already exists, sends PATCH to update.
182
+ * Otherwise queues params for next session request.
172
183
  */
173
- setParams(params) {
184
+ async setParams(params) {
174
185
  this.customParams = __spreadValues(__spreadValues({}, this.customParams), params);
186
+ if (this.sessionCreated && this.sessionId) {
187
+ await this.patchSession(params);
188
+ }
189
+ }
190
+ /**
191
+ * Get the currently queued custom params.
192
+ */
193
+ getQueuedParams() {
194
+ return __spreadValues({}, this.customParams);
195
+ }
196
+ async patchSession(params) {
197
+ try {
198
+ const response = await fetch(
199
+ `${this.config.endpoint}/v1/tracking/session/${this.sessionId}`,
200
+ {
201
+ method: "PATCH",
202
+ headers: { "Content-Type": "application/json" },
203
+ body: JSON.stringify(params)
204
+ }
205
+ );
206
+ if (!response.ok) {
207
+ console.warn("[CallForge] Failed to patch session:", response.status);
208
+ }
209
+ } catch (error) {
210
+ console.warn("[CallForge] Failed to patch session:", error);
211
+ }
212
+ }
213
+ /**
214
+ * Start polling for the GA4 _ga cookie.
215
+ * If found immediately, calls setParams right away.
216
+ * Otherwise polls every 500ms for up to 10 seconds.
217
+ */
218
+ startGA4CookiePolling() {
219
+ if (this.ga4PollInterval !== null || this.ga4PollTimeout !== null) {
220
+ return;
221
+ }
222
+ const clientId = getGA4ClientId();
223
+ if (clientId) {
224
+ this.setParams({ ga4ClientId: clientId });
225
+ return;
226
+ }
227
+ this.ga4PollInterval = setInterval(() => {
228
+ const clientId2 = getGA4ClientId();
229
+ if (clientId2) {
230
+ this.setParams({ ga4ClientId: clientId2 });
231
+ this.stopGA4CookiePolling();
232
+ }
233
+ }, 500);
234
+ this.ga4PollTimeout = setTimeout(() => {
235
+ this.stopGA4CookiePolling();
236
+ }, 1e4);
237
+ }
238
+ stopGA4CookiePolling() {
239
+ if (this.ga4PollInterval) {
240
+ clearInterval(this.ga4PollInterval);
241
+ this.ga4PollInterval = null;
242
+ }
243
+ if (this.ga4PollTimeout) {
244
+ clearTimeout(this.ga4PollTimeout);
245
+ this.ga4PollTimeout = null;
246
+ }
175
247
  }
176
248
  async fetchSession() {
177
249
  const locationId = this.getLocationId();
178
250
  if (locationId) {
179
251
  const cached = this.cache.get(locationId);
180
252
  if (cached) {
253
+ this.sessionId = cached.sessionId;
254
+ this.sessionCreated = true;
181
255
  return this.formatSession(cached);
182
256
  }
183
257
  }
@@ -188,15 +262,19 @@ var CallForge = class _CallForge {
188
262
  try {
189
263
  const data2 = await window.__cfTracking;
190
264
  this.saveToCache(locationId, data2, params);
265
+ this.sessionId = data2.sessionId;
266
+ this.sessionCreated = true;
191
267
  return this.formatApiResponse(data2);
192
268
  } catch (e) {
193
269
  }
194
270
  }
195
- const sessionId = locationId ? this.cache.getSessionId(locationId) : null;
196
- const data = await this.fetchFromApi(locationId, sessionId, params);
271
+ const cachedSessionId = locationId ? this.cache.getSessionId(locationId) : null;
272
+ const data = await this.fetchFromApi(locationId, cachedSessionId, params);
197
273
  if (locationId) {
198
274
  this.saveToCache(locationId, data, params);
199
275
  }
276
+ this.sessionId = data.sessionId;
277
+ this.sessionCreated = true;
200
278
  return this.formatApiResponse(data);
201
279
  }
202
280
  getLocationId() {
package/dist/index.mjs CHANGED
@@ -105,17 +105,27 @@ var TrackingCache = class {
105
105
 
106
106
  // src/client.ts
107
107
  var DEFAULT_ENDPOINT = "https://tracking.callforge.io";
108
+ function getGA4ClientId() {
109
+ if (typeof document === "undefined") return null;
110
+ const match = document.cookie.match(/_ga=GA\d+\.\d+\.(.+?)(?:;|$)/);
111
+ return match ? match[1] : null;
112
+ }
108
113
  var FETCH_TIMEOUT_MS = 1e4;
109
114
  var AUTO_PARAMS = ["gclid", "gbraid", "wbraid", "msclkid", "fbclid"];
110
115
  var CallForge = class _CallForge {
111
116
  constructor(config) {
112
117
  this.sessionPromise = null;
113
118
  this.customParams = {};
119
+ this.ga4PollInterval = null;
120
+ this.ga4PollTimeout = null;
121
+ this.sessionId = null;
122
+ this.sessionCreated = false;
114
123
  this.config = {
115
124
  categoryId: config.categoryId,
116
125
  endpoint: config.endpoint || DEFAULT_ENDPOINT
117
126
  };
118
127
  this.cache = new TrackingCache(config.categoryId);
128
+ this.startGA4CookiePolling();
119
129
  }
120
130
  /**
121
131
  * Initialize the CallForge tracking client.
@@ -144,16 +154,80 @@ var CallForge = class _CallForge {
144
154
  }
145
155
  /**
146
156
  * Set custom tracking parameters.
147
- * Merges with existing params (new values override).
157
+ * If session already exists, sends PATCH to update.
158
+ * Otherwise queues params for next session request.
148
159
  */
149
- setParams(params) {
160
+ async setParams(params) {
150
161
  this.customParams = __spreadValues(__spreadValues({}, this.customParams), params);
162
+ if (this.sessionCreated && this.sessionId) {
163
+ await this.patchSession(params);
164
+ }
165
+ }
166
+ /**
167
+ * Get the currently queued custom params.
168
+ */
169
+ getQueuedParams() {
170
+ return __spreadValues({}, this.customParams);
171
+ }
172
+ async patchSession(params) {
173
+ try {
174
+ const response = await fetch(
175
+ `${this.config.endpoint}/v1/tracking/session/${this.sessionId}`,
176
+ {
177
+ method: "PATCH",
178
+ headers: { "Content-Type": "application/json" },
179
+ body: JSON.stringify(params)
180
+ }
181
+ );
182
+ if (!response.ok) {
183
+ console.warn("[CallForge] Failed to patch session:", response.status);
184
+ }
185
+ } catch (error) {
186
+ console.warn("[CallForge] Failed to patch session:", error);
187
+ }
188
+ }
189
+ /**
190
+ * Start polling for the GA4 _ga cookie.
191
+ * If found immediately, calls setParams right away.
192
+ * Otherwise polls every 500ms for up to 10 seconds.
193
+ */
194
+ startGA4CookiePolling() {
195
+ if (this.ga4PollInterval !== null || this.ga4PollTimeout !== null) {
196
+ return;
197
+ }
198
+ const clientId = getGA4ClientId();
199
+ if (clientId) {
200
+ this.setParams({ ga4ClientId: clientId });
201
+ return;
202
+ }
203
+ this.ga4PollInterval = setInterval(() => {
204
+ const clientId2 = getGA4ClientId();
205
+ if (clientId2) {
206
+ this.setParams({ ga4ClientId: clientId2 });
207
+ this.stopGA4CookiePolling();
208
+ }
209
+ }, 500);
210
+ this.ga4PollTimeout = setTimeout(() => {
211
+ this.stopGA4CookiePolling();
212
+ }, 1e4);
213
+ }
214
+ stopGA4CookiePolling() {
215
+ if (this.ga4PollInterval) {
216
+ clearInterval(this.ga4PollInterval);
217
+ this.ga4PollInterval = null;
218
+ }
219
+ if (this.ga4PollTimeout) {
220
+ clearTimeout(this.ga4PollTimeout);
221
+ this.ga4PollTimeout = null;
222
+ }
151
223
  }
152
224
  async fetchSession() {
153
225
  const locationId = this.getLocationId();
154
226
  if (locationId) {
155
227
  const cached = this.cache.get(locationId);
156
228
  if (cached) {
229
+ this.sessionId = cached.sessionId;
230
+ this.sessionCreated = true;
157
231
  return this.formatSession(cached);
158
232
  }
159
233
  }
@@ -164,15 +238,19 @@ var CallForge = class _CallForge {
164
238
  try {
165
239
  const data2 = await window.__cfTracking;
166
240
  this.saveToCache(locationId, data2, params);
241
+ this.sessionId = data2.sessionId;
242
+ this.sessionCreated = true;
167
243
  return this.formatApiResponse(data2);
168
244
  } catch (e) {
169
245
  }
170
246
  }
171
- const sessionId = locationId ? this.cache.getSessionId(locationId) : null;
172
- const data = await this.fetchFromApi(locationId, sessionId, params);
247
+ const cachedSessionId = locationId ? this.cache.getSessionId(locationId) : null;
248
+ const data = await this.fetchFromApi(locationId, cachedSessionId, params);
173
249
  if (locationId) {
174
250
  this.saveToCache(locationId, data, params);
175
251
  }
252
+ this.sessionId = data.sessionId;
253
+ this.sessionCreated = true;
176
254
  return this.formatApiResponse(data);
177
255
  }
178
256
  getLocationId() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callforge/tracking-client",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,17 +14,17 @@
14
14
  "files": [
15
15
  "dist"
16
16
  ],
17
- "devDependencies": {
18
- "jsdom": "^27.4.0",
19
- "tsup": "^8.0.0",
20
- "typescript": "^5.3.0",
21
- "vitest": "^1.6.0",
22
- "@callforge/tsconfig": "0.0.0"
23
- },
24
17
  "scripts": {
25
18
  "build": "tsup src/index.ts --format esm,cjs --dts",
26
19
  "clean": "rm -rf dist",
27
20
  "test": "vitest run",
28
21
  "test:watch": "vitest"
22
+ },
23
+ "devDependencies": {
24
+ "@callforge/tsconfig": "workspace:*",
25
+ "jsdom": "^27.4.0",
26
+ "tsup": "^8.0.0",
27
+ "typescript": "^5.3.0",
28
+ "vitest": "^1.6.0"
29
29
  }
30
- }
30
+ }