@callforge/tracking-client 0.9.0 → 0.9.2

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
@@ -122,6 +122,7 @@ Notes:
122
122
  - `linkPhoneCall` is optimized for mobile tap-to-call timing.
123
123
  - `setWebZip` accepts `manual` (typed) and `suggested` (picked from options).
124
124
  - `setWebZip` validates ZIP format (`12345`) client-side before sending.
125
+ - `setWebZip` also sends `webZip` as a custom session param in a best-effort sync backup path.
125
126
 
126
127
  ### 5. GA4 Integration
127
128
 
@@ -286,7 +287,7 @@ if (result.status === 'ready') {
286
287
  Behavior:
287
288
  - Rejects invalid ZIP values unless they are 5 digits.
288
289
  - Writes profile data keyed by `sessionId`.
289
- - Also mirrors `webZip` and `webZipSource` into queued params for subsequent session refreshes.
290
+ - Also mirrors `webZip` and `webZipSource` into custom params and triggers a best-effort session sync backup.
290
291
 
291
292
  ### `client.onReady(callback)`
292
293
 
package/dist/index.js CHANGED
@@ -329,11 +329,17 @@ var CallForge = class _CallForge {
329
329
  * Write visitor-selected web ZIP to the realtime data layer.
330
330
  */
331
331
  async setWebZip(zipCode, options) {
332
+ var _a;
332
333
  const normalizedZip = zipCode.trim();
333
334
  if (!ZIP_CODE_PATTERN.test(normalizedZip)) {
334
335
  throw new Error("Invalid ZIP code. Expected a 5-digit ZIP.");
335
336
  }
336
337
  const session = await this.getSession();
338
+ const fallbackSource = (_a = options == null ? void 0 : options.source) != null ? _a : "manual";
339
+ void this.setParams({
340
+ webZip: normalizedZip,
341
+ webZipSource: fallbackSource
342
+ });
337
343
  const controller = new AbortController();
338
344
  const timeoutId = setTimeout(() => controller.abort(), REALTIME_PROFILE_TIMEOUT_MS);
339
345
  try {
@@ -547,8 +553,11 @@ var CallForge = class _CallForge {
547
553
  async fetchFromApi(locationId, sessionToken, params) {
548
554
  const controller = new AbortController();
549
555
  const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
556
+ let didForceRefreshBootstrap = false;
557
+ let usedBootstrapTokenInInitialRequest = false;
550
558
  try {
551
559
  let bootstrapToken = this.getCachedBootstrapToken();
560
+ usedBootstrapTokenInInitialRequest = !!bootstrapToken;
552
561
  let response = await fetch(
553
562
  this.buildUrl(locationId, sessionToken, params, bootstrapToken),
554
563
  {
@@ -558,6 +567,7 @@ var CallForge = class _CallForge {
558
567
  );
559
568
  if (response.status === 401) {
560
569
  bootstrapToken = await this.getBootstrapToken(true);
570
+ didForceRefreshBootstrap = true;
561
571
  if (bootstrapToken) {
562
572
  response = await fetch(
563
573
  this.buildUrl(locationId, sessionToken, params, bootstrapToken),
@@ -571,7 +581,24 @@ var CallForge = class _CallForge {
571
581
  if (!response.ok) {
572
582
  throw new Error(`API error: ${response.status} ${response.statusText}`);
573
583
  }
574
- return await response.json();
584
+ let data = await response.json();
585
+ if (data.leaseId === null && !usedBootstrapTokenInInitialRequest && !didForceRefreshBootstrap) {
586
+ const refreshedBootstrapToken = await this.getBootstrapToken(true);
587
+ didForceRefreshBootstrap = true;
588
+ if (refreshedBootstrapToken) {
589
+ const retryResponse = await fetch(
590
+ this.buildUrl(locationId, sessionToken, params, refreshedBootstrapToken),
591
+ {
592
+ credentials: "omit",
593
+ signal: controller.signal
594
+ }
595
+ );
596
+ if (retryResponse.ok) {
597
+ data = await retryResponse.json();
598
+ }
599
+ }
600
+ }
601
+ return data;
575
602
  } finally {
576
603
  clearTimeout(timeoutId);
577
604
  }
package/dist/index.mjs CHANGED
@@ -305,11 +305,17 @@ var CallForge = class _CallForge {
305
305
  * Write visitor-selected web ZIP to the realtime data layer.
306
306
  */
307
307
  async setWebZip(zipCode, options) {
308
+ var _a;
308
309
  const normalizedZip = zipCode.trim();
309
310
  if (!ZIP_CODE_PATTERN.test(normalizedZip)) {
310
311
  throw new Error("Invalid ZIP code. Expected a 5-digit ZIP.");
311
312
  }
312
313
  const session = await this.getSession();
314
+ const fallbackSource = (_a = options == null ? void 0 : options.source) != null ? _a : "manual";
315
+ void this.setParams({
316
+ webZip: normalizedZip,
317
+ webZipSource: fallbackSource
318
+ });
313
319
  const controller = new AbortController();
314
320
  const timeoutId = setTimeout(() => controller.abort(), REALTIME_PROFILE_TIMEOUT_MS);
315
321
  try {
@@ -523,8 +529,11 @@ var CallForge = class _CallForge {
523
529
  async fetchFromApi(locationId, sessionToken, params) {
524
530
  const controller = new AbortController();
525
531
  const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
532
+ let didForceRefreshBootstrap = false;
533
+ let usedBootstrapTokenInInitialRequest = false;
526
534
  try {
527
535
  let bootstrapToken = this.getCachedBootstrapToken();
536
+ usedBootstrapTokenInInitialRequest = !!bootstrapToken;
528
537
  let response = await fetch(
529
538
  this.buildUrl(locationId, sessionToken, params, bootstrapToken),
530
539
  {
@@ -534,6 +543,7 @@ var CallForge = class _CallForge {
534
543
  );
535
544
  if (response.status === 401) {
536
545
  bootstrapToken = await this.getBootstrapToken(true);
546
+ didForceRefreshBootstrap = true;
537
547
  if (bootstrapToken) {
538
548
  response = await fetch(
539
549
  this.buildUrl(locationId, sessionToken, params, bootstrapToken),
@@ -547,7 +557,24 @@ var CallForge = class _CallForge {
547
557
  if (!response.ok) {
548
558
  throw new Error(`API error: ${response.status} ${response.statusText}`);
549
559
  }
550
- return await response.json();
560
+ let data = await response.json();
561
+ if (data.leaseId === null && !usedBootstrapTokenInInitialRequest && !didForceRefreshBootstrap) {
562
+ const refreshedBootstrapToken = await this.getBootstrapToken(true);
563
+ didForceRefreshBootstrap = true;
564
+ if (refreshedBootstrapToken) {
565
+ const retryResponse = await fetch(
566
+ this.buildUrl(locationId, sessionToken, params, refreshedBootstrapToken),
567
+ {
568
+ credentials: "omit",
569
+ signal: controller.signal
570
+ }
571
+ );
572
+ if (retryResponse.ok) {
573
+ data = await retryResponse.json();
574
+ }
575
+ }
576
+ }
577
+ return data;
551
578
  } finally {
552
579
  clearTimeout(timeoutId);
553
580
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callforge/tracking-client",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",