@callforge/tracking-client 0.0.1 → 0.1.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 CHANGED
@@ -51,6 +51,29 @@ client.onReady((session) => {
51
51
  });
52
52
  ```
53
53
 
54
+ ### 3. Track conversion parameters (optional)
55
+
56
+ The client automatically captures ad platform click IDs from the URL:
57
+
58
+ - `gclid` - Google Ads
59
+ - `gbraid` - Google app-to-web (iOS 14+)
60
+ - `wbraid` - Google web-to-app
61
+ - `msclkid` - Microsoft/Bing Ads
62
+ - `fbclid` - Facebook/Meta Ads
63
+
64
+ You can also add custom parameters:
65
+
66
+ ```typescript
67
+ // Add custom tracking parameters
68
+ client.setParams({
69
+ customerId: '456',
70
+ landingPage: 'pricing',
71
+ });
72
+
73
+ // Parameters are automatically sent with every API request
74
+ const session = await client.getSession();
75
+ ```
76
+
54
77
  ## API Reference
55
78
 
56
79
  ### `CallForge.init(config)`
@@ -96,6 +119,24 @@ client.onReady((session) => {
96
119
  });
97
120
  ```
98
121
 
122
+ ### `client.setParams(params)`
123
+
124
+ Set custom tracking parameters for conversion attribution.
125
+
126
+ ```typescript
127
+ client.setParams({
128
+ customerId: '456',
129
+ landingPage: 'pricing',
130
+ campaign: 'summer-sale',
131
+ });
132
+ ```
133
+
134
+ **Behavior:**
135
+ - Merges with existing params (later calls override earlier values)
136
+ - Parameters are sent with every `getSession()` API request
137
+ - Persisted in localStorage alongside session data
138
+ - Auto-captured params (gclid, etc.) are included automatically
139
+
99
140
  ### `getPreloadSnippet(config)`
100
141
 
101
142
  Generate HTML snippet for preloading tracking data.
@@ -109,6 +150,35 @@ const html = getPreloadSnippet({
109
150
  });
110
151
  ```
111
152
 
153
+ ## Tracking Parameters
154
+
155
+ ### Auto-Capture
156
+
157
+ The client automatically extracts these parameters from the URL on first visit:
158
+
159
+ | Parameter | Source |
160
+ |-----------|--------|
161
+ | `gclid` | Google Ads Click ID |
162
+ | `gbraid` | Google app-to-web (iOS 14+) |
163
+ | `wbraid` | Google web-to-app |
164
+ | `msclkid` | Microsoft/Bing Ads |
165
+ | `fbclid` | Facebook/Meta Ads |
166
+
167
+ ### Persistence
168
+
169
+ - Parameters are stored in localStorage alongside the session
170
+ - On subsequent visits, cached params are used (URL may no longer have them)
171
+ - Custom params via `setParams()` merge with auto-captured params
172
+ - Later values override earlier ones (custom > cached > auto-captured)
173
+
174
+ ### API Request Format
175
+
176
+ Parameters are sent as sorted query string for cache consistency:
177
+
178
+ ```
179
+ /v1/tracking/session?categoryId=cat-123&fbclid=456&gclid=abc&loc_physical_ms=1014221
180
+ ```
181
+
112
182
  ## Caching Behavior
113
183
 
114
184
  - **Cache key:** `loc_physical_ms` parameter from URL
@@ -141,10 +211,24 @@ import type {
141
211
  CallForgeConfig,
142
212
  TrackingSession,
143
213
  TrackingLocation,
214
+ TrackingParams,
144
215
  ReadyCallback,
145
216
  } from '@callforge/tracking-client';
146
217
  ```
147
218
 
219
+ ### TrackingParams
220
+
221
+ ```typescript
222
+ interface TrackingParams {
223
+ gclid?: string; // Google Ads Click ID
224
+ gbraid?: string; // Google app-to-web (iOS 14+)
225
+ wbraid?: string; // Google web-to-app
226
+ msclkid?: string; // Microsoft/Bing Ads
227
+ fbclid?: string; // Facebook/Meta Ads
228
+ [key: string]: string | undefined; // Custom params
229
+ }
230
+ ```
231
+
148
232
  ## Environment URLs
149
233
 
150
234
  | Environment | Endpoint |
package/dist/index.d.mts CHANGED
@@ -18,6 +18,23 @@ interface TrackingLocation {
18
18
  /** State abbreviation (e.g., "GA") */
19
19
  stateCode: string;
20
20
  }
21
+ /**
22
+ * Tracking parameters for attribution (auto-captured + custom).
23
+ */
24
+ interface TrackingParams {
25
+ /** Google Ads Click ID */
26
+ gclid?: string;
27
+ /** Google app-to-web (iOS 14+) */
28
+ gbraid?: string;
29
+ /** Google web-to-app */
30
+ wbraid?: string;
31
+ /** Microsoft/Bing Ads Click ID */
32
+ msclkid?: string;
33
+ /** Facebook/Meta Ads Click ID */
34
+ fbclid?: string;
35
+ /** Custom parameters */
36
+ [key: string]: string | undefined;
37
+ }
21
38
  /**
22
39
  * Session data returned by getSession().
23
40
  */
@@ -59,6 +76,7 @@ declare class CallForge {
59
76
  private readonly config;
60
77
  private readonly cache;
61
78
  private sessionPromise;
79
+ private customParams;
62
80
  private constructor();
63
81
  /**
64
82
  * Initialize the CallForge tracking client.
@@ -74,12 +92,19 @@ declare class CallForge {
74
92
  * Callback is called once session data is available.
75
93
  */
76
94
  onReady(callback: ReadyCallback): void;
95
+ /**
96
+ * Set custom tracking parameters.
97
+ * Merges with existing params (new values override).
98
+ */
99
+ setParams(params: Record<string, string>): void;
77
100
  private fetchSession;
78
101
  private getLocationId;
102
+ private getAutoParams;
79
103
  private fetchFromApi;
80
104
  private saveToCache;
81
105
  private formatSession;
82
106
  private formatApiResponse;
107
+ private buildUrl;
83
108
  }
84
109
 
85
110
  /**
@@ -99,4 +124,4 @@ declare class CallForge {
99
124
  */
100
125
  declare function getPreloadSnippet(config: CallForgeConfig): string;
101
126
 
102
- export { CallForge, type CallForgeConfig, type ReadyCallback, type TrackingLocation, type TrackingSession, getPreloadSnippet };
127
+ export { CallForge, type CallForgeConfig, type ReadyCallback, type TrackingLocation, type TrackingParams, type TrackingSession, getPreloadSnippet };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,23 @@ interface TrackingLocation {
18
18
  /** State abbreviation (e.g., "GA") */
19
19
  stateCode: string;
20
20
  }
21
+ /**
22
+ * Tracking parameters for attribution (auto-captured + custom).
23
+ */
24
+ interface TrackingParams {
25
+ /** Google Ads Click ID */
26
+ gclid?: string;
27
+ /** Google app-to-web (iOS 14+) */
28
+ gbraid?: string;
29
+ /** Google web-to-app */
30
+ wbraid?: string;
31
+ /** Microsoft/Bing Ads Click ID */
32
+ msclkid?: string;
33
+ /** Facebook/Meta Ads Click ID */
34
+ fbclid?: string;
35
+ /** Custom parameters */
36
+ [key: string]: string | undefined;
37
+ }
21
38
  /**
22
39
  * Session data returned by getSession().
23
40
  */
@@ -59,6 +76,7 @@ declare class CallForge {
59
76
  private readonly config;
60
77
  private readonly cache;
61
78
  private sessionPromise;
79
+ private customParams;
62
80
  private constructor();
63
81
  /**
64
82
  * Initialize the CallForge tracking client.
@@ -74,12 +92,19 @@ declare class CallForge {
74
92
  * Callback is called once session data is available.
75
93
  */
76
94
  onReady(callback: ReadyCallback): void;
95
+ /**
96
+ * Set custom tracking parameters.
97
+ * Merges with existing params (new values override).
98
+ */
99
+ setParams(params: Record<string, string>): void;
77
100
  private fetchSession;
78
101
  private getLocationId;
102
+ private getAutoParams;
79
103
  private fetchFromApi;
80
104
  private saveToCache;
81
105
  private formatSession;
82
106
  private formatApiResponse;
107
+ private buildUrl;
83
108
  }
84
109
 
85
110
  /**
@@ -99,4 +124,4 @@ declare class CallForge {
99
124
  */
100
125
  declare function getPreloadSnippet(config: CallForgeConfig): string;
101
126
 
102
- export { CallForge, type CallForgeConfig, type ReadyCallback, type TrackingLocation, type TrackingSession, getPreloadSnippet };
127
+ export { CallForge, type CallForgeConfig, type ReadyCallback, type TrackingLocation, type TrackingParams, type TrackingSession, getPreloadSnippet };
package/dist/index.js CHANGED
@@ -2,7 +2,21 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
6
20
  var __export = (target, all) => {
7
21
  for (var name in all)
8
22
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -64,6 +78,15 @@ var TrackingCache = class {
64
78
  if (cached.locId !== locationId) return null;
65
79
  return cached.sessionId;
66
80
  }
81
+ /**
82
+ * Get cached params (for merging with new params).
83
+ * Returns empty object if no cache or no params.
84
+ */
85
+ getParams() {
86
+ var _a;
87
+ const cached = this.read();
88
+ return (_a = cached == null ? void 0 : cached.params) != null ? _a : {};
89
+ }
67
90
  /**
68
91
  * Store session data in cache.
69
92
  */
@@ -107,9 +130,11 @@ var TrackingCache = class {
107
130
  // src/client.ts
108
131
  var DEFAULT_ENDPOINT = "https://tracking.callforge.io";
109
132
  var FETCH_TIMEOUT_MS = 1e4;
133
+ var AUTO_PARAMS = ["gclid", "gbraid", "wbraid", "msclkid", "fbclid"];
110
134
  var CallForge = class _CallForge {
111
135
  constructor(config) {
112
136
  this.sessionPromise = null;
137
+ this.customParams = {};
113
138
  this.config = {
114
139
  categoryId: config.categoryId,
115
140
  endpoint: config.endpoint || DEFAULT_ENDPOINT
@@ -141,6 +166,13 @@ var CallForge = class _CallForge {
141
166
  this.getSession().then(callback).catch(() => {
142
167
  });
143
168
  }
169
+ /**
170
+ * Set custom tracking parameters.
171
+ * Merges with existing params (new values override).
172
+ */
173
+ setParams(params) {
174
+ this.customParams = __spreadValues(__spreadValues({}, this.customParams), params);
175
+ }
144
176
  async fetchSession() {
145
177
  const locationId = this.getLocationId();
146
178
  if (!locationId) {
@@ -150,17 +182,20 @@ var CallForge = class _CallForge {
150
182
  if (cached) {
151
183
  return this.formatSession(cached);
152
184
  }
185
+ const autoParams = this.getAutoParams();
186
+ const cachedParams = this.cache.getParams();
187
+ const params = __spreadValues(__spreadValues(__spreadValues({}, autoParams), cachedParams), this.customParams);
153
188
  if (typeof window !== "undefined" && window.__cfTracking) {
154
189
  try {
155
190
  const data2 = await window.__cfTracking;
156
- this.saveToCache(locationId, data2);
191
+ this.saveToCache(locationId, data2, params);
157
192
  return this.formatApiResponse(data2);
158
193
  } catch (e) {
159
194
  }
160
195
  }
161
196
  const sessionId = this.cache.getSessionId(locationId);
162
- const data = await this.fetchFromApi(locationId, sessionId);
163
- this.saveToCache(locationId, data);
197
+ const data = await this.fetchFromApi(locationId, sessionId, params);
198
+ this.saveToCache(locationId, data, params);
164
199
  return this.formatApiResponse(data);
165
200
  }
166
201
  getLocationId() {
@@ -168,12 +203,20 @@ var CallForge = class _CallForge {
168
203
  const params = new URLSearchParams(window.location.search);
169
204
  return params.get("loc_physical_ms");
170
205
  }
171
- async fetchFromApi(locationId, sessionId) {
172
- const { categoryId, endpoint } = this.config;
173
- let url = `${endpoint}/v1/tracking/session?categoryId=${categoryId}&loc_physical_ms=${locationId}`;
174
- if (sessionId) {
175
- url += `&sessionId=${sessionId}`;
206
+ getAutoParams() {
207
+ if (typeof window === "undefined") return {};
208
+ const urlParams = new URLSearchParams(window.location.search);
209
+ const params = {};
210
+ for (const key of AUTO_PARAMS) {
211
+ const value = urlParams.get(key);
212
+ if (value) {
213
+ params[key] = value;
214
+ }
176
215
  }
216
+ return params;
217
+ }
218
+ async fetchFromApi(locationId, sessionId, params) {
219
+ const url = this.buildUrl(locationId, sessionId, params);
177
220
  const controller = new AbortController();
178
221
  const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
179
222
  try {
@@ -189,13 +232,14 @@ var CallForge = class _CallForge {
189
232
  clearTimeout(timeoutId);
190
233
  }
191
234
  }
192
- saveToCache(locationId, data) {
235
+ saveToCache(locationId, data, params) {
193
236
  const cached = {
194
237
  locId: locationId,
195
238
  sessionId: data.sessionId,
196
239
  phoneNumber: data.phoneNumber,
197
240
  location: data.location,
198
- expiresAt: data.expiresAt
241
+ expiresAt: data.expiresAt,
242
+ params
199
243
  };
200
244
  this.cache.set(cached);
201
245
  }
@@ -213,6 +257,24 @@ var CallForge = class _CallForge {
213
257
  location: data.location
214
258
  };
215
259
  }
260
+ buildUrl(locationId, sessionId, params) {
261
+ const { categoryId, endpoint } = this.config;
262
+ const queryParams = {
263
+ categoryId,
264
+ loc_physical_ms: locationId
265
+ };
266
+ if (sessionId) {
267
+ queryParams.sessionId = sessionId;
268
+ }
269
+ for (const [key, value] of Object.entries(params)) {
270
+ if (value !== void 0) {
271
+ queryParams[key] = value;
272
+ }
273
+ }
274
+ const sorted = Object.keys(queryParams).sort();
275
+ const qs = sorted.map((k) => `${k}=${encodeURIComponent(queryParams[k])}`).join("&");
276
+ return `${endpoint}/v1/tracking/session?${qs}`;
277
+ }
216
278
  };
217
279
 
218
280
  // src/preload.ts
@@ -234,17 +296,25 @@ function getPreloadSnippet(config) {
234
296
  }
235
297
  const cacheKey = `cf_tracking_${categoryId}`;
236
298
  const script = `(function(){
237
- var loc=new URLSearchParams(location.search).get('loc_physical_ms');
299
+ var u=new URLSearchParams(location.search);
300
+ var loc=u.get('loc_physical_ms');
238
301
  if(!loc)return;
302
+ var ap=['gclid','gbraid','wbraid','msclkid','fbclid'];
303
+ var p={};
304
+ for(var i=0;i<ap.length;i++){var v=u.get(ap[i]);if(v)p[ap[i]]=v}
239
305
  var key='${cacheKey}';
240
306
  try{
241
307
  var c=JSON.parse(localStorage.getItem(key));
242
- if(c&&c.locId===loc&&c.expiresAt>Date.now()+30000){window.__cfTracking=Promise.resolve(c);return}
308
+ if(c&&c.locId===loc&&c.expiresAt>Date.now()+30000){c.params=Object.assign({},c.params,p);window.__cfTracking=Promise.resolve(c);return}
243
309
  var sid=(c&&c.locId===loc)?c.sessionId:null;
310
+ var cp=c&&c.params||{};
311
+ p=Object.assign({},p,cp);
244
312
  }catch(e){}
245
313
  var url='${endpoint}/v1/tracking/session?categoryId=${categoryId}&loc_physical_ms='+loc;
246
314
  if(sid)url+='&sessionId='+sid;
247
- window.__cfTracking=fetch(url,{credentials:'omit'}).then(function(r){return r.json()});
315
+ var ks=Object.keys(p).sort();
316
+ for(var j=0;j<ks.length;j++)url+='&'+ks[j]+'='+encodeURIComponent(p[ks[j]]);
317
+ window.__cfTracking=fetch(url,{credentials:'omit'}).then(function(r){return r.json()}).then(function(d){d.params=p;try{localStorage.setItem(key,JSON.stringify({locId:loc,sessionId:d.sessionId,phoneNumber:d.phoneNumber,location:d.location,expiresAt:d.expiresAt,params:p}))}catch(e){}return d});
248
318
  })();`.replace(/\n/g, "");
249
319
  return `<link rel="preconnect" href="${endpoint}">
250
320
  <script>${script}</script>`;
package/dist/index.mjs CHANGED
@@ -1,3 +1,20 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
17
+
1
18
  // src/cache.ts
2
19
  var EXPIRY_BUFFER_MS = 3e4;
3
20
  var TrackingCache = class {
@@ -37,6 +54,15 @@ var TrackingCache = class {
37
54
  if (cached.locId !== locationId) return null;
38
55
  return cached.sessionId;
39
56
  }
57
+ /**
58
+ * Get cached params (for merging with new params).
59
+ * Returns empty object if no cache or no params.
60
+ */
61
+ getParams() {
62
+ var _a;
63
+ const cached = this.read();
64
+ return (_a = cached == null ? void 0 : cached.params) != null ? _a : {};
65
+ }
40
66
  /**
41
67
  * Store session data in cache.
42
68
  */
@@ -80,9 +106,11 @@ var TrackingCache = class {
80
106
  // src/client.ts
81
107
  var DEFAULT_ENDPOINT = "https://tracking.callforge.io";
82
108
  var FETCH_TIMEOUT_MS = 1e4;
109
+ var AUTO_PARAMS = ["gclid", "gbraid", "wbraid", "msclkid", "fbclid"];
83
110
  var CallForge = class _CallForge {
84
111
  constructor(config) {
85
112
  this.sessionPromise = null;
113
+ this.customParams = {};
86
114
  this.config = {
87
115
  categoryId: config.categoryId,
88
116
  endpoint: config.endpoint || DEFAULT_ENDPOINT
@@ -114,6 +142,13 @@ var CallForge = class _CallForge {
114
142
  this.getSession().then(callback).catch(() => {
115
143
  });
116
144
  }
145
+ /**
146
+ * Set custom tracking parameters.
147
+ * Merges with existing params (new values override).
148
+ */
149
+ setParams(params) {
150
+ this.customParams = __spreadValues(__spreadValues({}, this.customParams), params);
151
+ }
117
152
  async fetchSession() {
118
153
  const locationId = this.getLocationId();
119
154
  if (!locationId) {
@@ -123,17 +158,20 @@ var CallForge = class _CallForge {
123
158
  if (cached) {
124
159
  return this.formatSession(cached);
125
160
  }
161
+ const autoParams = this.getAutoParams();
162
+ const cachedParams = this.cache.getParams();
163
+ const params = __spreadValues(__spreadValues(__spreadValues({}, autoParams), cachedParams), this.customParams);
126
164
  if (typeof window !== "undefined" && window.__cfTracking) {
127
165
  try {
128
166
  const data2 = await window.__cfTracking;
129
- this.saveToCache(locationId, data2);
167
+ this.saveToCache(locationId, data2, params);
130
168
  return this.formatApiResponse(data2);
131
169
  } catch (e) {
132
170
  }
133
171
  }
134
172
  const sessionId = this.cache.getSessionId(locationId);
135
- const data = await this.fetchFromApi(locationId, sessionId);
136
- this.saveToCache(locationId, data);
173
+ const data = await this.fetchFromApi(locationId, sessionId, params);
174
+ this.saveToCache(locationId, data, params);
137
175
  return this.formatApiResponse(data);
138
176
  }
139
177
  getLocationId() {
@@ -141,12 +179,20 @@ var CallForge = class _CallForge {
141
179
  const params = new URLSearchParams(window.location.search);
142
180
  return params.get("loc_physical_ms");
143
181
  }
144
- async fetchFromApi(locationId, sessionId) {
145
- const { categoryId, endpoint } = this.config;
146
- let url = `${endpoint}/v1/tracking/session?categoryId=${categoryId}&loc_physical_ms=${locationId}`;
147
- if (sessionId) {
148
- url += `&sessionId=${sessionId}`;
182
+ getAutoParams() {
183
+ if (typeof window === "undefined") return {};
184
+ const urlParams = new URLSearchParams(window.location.search);
185
+ const params = {};
186
+ for (const key of AUTO_PARAMS) {
187
+ const value = urlParams.get(key);
188
+ if (value) {
189
+ params[key] = value;
190
+ }
149
191
  }
192
+ return params;
193
+ }
194
+ async fetchFromApi(locationId, sessionId, params) {
195
+ const url = this.buildUrl(locationId, sessionId, params);
150
196
  const controller = new AbortController();
151
197
  const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
152
198
  try {
@@ -162,13 +208,14 @@ var CallForge = class _CallForge {
162
208
  clearTimeout(timeoutId);
163
209
  }
164
210
  }
165
- saveToCache(locationId, data) {
211
+ saveToCache(locationId, data, params) {
166
212
  const cached = {
167
213
  locId: locationId,
168
214
  sessionId: data.sessionId,
169
215
  phoneNumber: data.phoneNumber,
170
216
  location: data.location,
171
- expiresAt: data.expiresAt
217
+ expiresAt: data.expiresAt,
218
+ params
172
219
  };
173
220
  this.cache.set(cached);
174
221
  }
@@ -186,6 +233,24 @@ var CallForge = class _CallForge {
186
233
  location: data.location
187
234
  };
188
235
  }
236
+ buildUrl(locationId, sessionId, params) {
237
+ const { categoryId, endpoint } = this.config;
238
+ const queryParams = {
239
+ categoryId,
240
+ loc_physical_ms: locationId
241
+ };
242
+ if (sessionId) {
243
+ queryParams.sessionId = sessionId;
244
+ }
245
+ for (const [key, value] of Object.entries(params)) {
246
+ if (value !== void 0) {
247
+ queryParams[key] = value;
248
+ }
249
+ }
250
+ const sorted = Object.keys(queryParams).sort();
251
+ const qs = sorted.map((k) => `${k}=${encodeURIComponent(queryParams[k])}`).join("&");
252
+ return `${endpoint}/v1/tracking/session?${qs}`;
253
+ }
189
254
  };
190
255
 
191
256
  // src/preload.ts
@@ -207,17 +272,25 @@ function getPreloadSnippet(config) {
207
272
  }
208
273
  const cacheKey = `cf_tracking_${categoryId}`;
209
274
  const script = `(function(){
210
- var loc=new URLSearchParams(location.search).get('loc_physical_ms');
275
+ var u=new URLSearchParams(location.search);
276
+ var loc=u.get('loc_physical_ms');
211
277
  if(!loc)return;
278
+ var ap=['gclid','gbraid','wbraid','msclkid','fbclid'];
279
+ var p={};
280
+ for(var i=0;i<ap.length;i++){var v=u.get(ap[i]);if(v)p[ap[i]]=v}
212
281
  var key='${cacheKey}';
213
282
  try{
214
283
  var c=JSON.parse(localStorage.getItem(key));
215
- if(c&&c.locId===loc&&c.expiresAt>Date.now()+30000){window.__cfTracking=Promise.resolve(c);return}
284
+ if(c&&c.locId===loc&&c.expiresAt>Date.now()+30000){c.params=Object.assign({},c.params,p);window.__cfTracking=Promise.resolve(c);return}
216
285
  var sid=(c&&c.locId===loc)?c.sessionId:null;
286
+ var cp=c&&c.params||{};
287
+ p=Object.assign({},p,cp);
217
288
  }catch(e){}
218
289
  var url='${endpoint}/v1/tracking/session?categoryId=${categoryId}&loc_physical_ms='+loc;
219
290
  if(sid)url+='&sessionId='+sid;
220
- window.__cfTracking=fetch(url,{credentials:'omit'}).then(function(r){return r.json()});
291
+ var ks=Object.keys(p).sort();
292
+ for(var j=0;j<ks.length;j++)url+='&'+ks[j]+'='+encodeURIComponent(p[ks[j]]);
293
+ window.__cfTracking=fetch(url,{credentials:'omit'}).then(function(r){return r.json()}).then(function(d){d.params=p;try{localStorage.setItem(key,JSON.stringify({locId:loc,sessionId:d.sessionId,phoneNumber:d.phoneNumber,location:d.location,expiresAt:d.expiresAt,params:p}))}catch(e){}return d});
221
294
  })();`.replace(/\n/g, "");
222
295
  return `<link rel="preconnect" href="${endpoint}">
223
296
  <script>${script}</script>`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callforge/tracking-client",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",