@callforge/tracking-client 0.8.0 → 0.9.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 +79 -2
- package/dist/index.d.mts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +77 -0
- package/dist/index.mjs +77 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,19 @@ Client integration requirements:
|
|
|
19
19
|
- Keep handling `phoneNumber` and `leaseId` separately. A request can return a phone number with `leaseId: null` when lease assignment is intentionally suppressed.
|
|
20
20
|
- For attribution/scale metrics, treat `leaseId` as the source of truth for lease-backed traffic.
|
|
21
21
|
|
|
22
|
+
## Realtime Data Layer Upgrade (v0.9+)
|
|
23
|
+
|
|
24
|
+
This release adds explicit browser helpers for the new realtime layer:
|
|
25
|
+
- `client.linkPhoneCall({ phoneNumber })` for strict web-click to phone-call linkage.
|
|
26
|
+
- `client.setWebZip(zipCode, { source })` for immediate web ZIP availability to call processing.
|
|
27
|
+
|
|
28
|
+
Integration checklist:
|
|
29
|
+
- Call `linkPhoneCall` immediately before opening a `tel:` link.
|
|
30
|
+
- Pass the exact dialed number string (`+1...`) used by the link.
|
|
31
|
+
- Continue dialing even if `linkPhoneCall` fails (best-effort attribution assist, not UX-blocking).
|
|
32
|
+
- Call `setWebZip` when the visitor selects or types a ZIP.
|
|
33
|
+
- Keep `setParams` for broader attribution params; use `setWebZip` for fast ZIP propagation.
|
|
34
|
+
|
|
22
35
|
## Quick Start
|
|
23
36
|
|
|
24
37
|
### 1. Add preload snippet to `<head>` (required for deterministic leases)
|
|
@@ -84,7 +97,33 @@ Notes:
|
|
|
84
97
|
- `callIntentToken` is short-lived and single-use.
|
|
85
98
|
- Treat it as an opaque secret (do not log it).
|
|
86
99
|
|
|
87
|
-
### 4.
|
|
100
|
+
### 4. Realtime call-link + web ZIP helpers (recommended)
|
|
101
|
+
|
|
102
|
+
Use explicit helpers to write realtime data from the browser.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const client = CallForge.init({ categoryId: 'your-category-id' });
|
|
106
|
+
|
|
107
|
+
async function dialTrackedNumber(phoneNumber: string) {
|
|
108
|
+
try {
|
|
109
|
+
// Default TTL is 30s (clamped server-side to 5-120s).
|
|
110
|
+
await client.linkPhoneCall({ phoneNumber });
|
|
111
|
+
} finally {
|
|
112
|
+
// Do not block dialing on telemetry failure.
|
|
113
|
+
window.location.href = `tel:${phoneNumber}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Example ZIP picker handler
|
|
118
|
+
await client.setWebZip('30309', { source: 'manual' });
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Notes:
|
|
122
|
+
- `linkPhoneCall` is optimized for mobile tap-to-call timing.
|
|
123
|
+
- `setWebZip` accepts `manual` (typed) and `suggested` (picked from options).
|
|
124
|
+
- `setWebZip` validates ZIP format (`12345`) client-side before sending.
|
|
125
|
+
|
|
126
|
+
### 5. GA4 Integration
|
|
88
127
|
|
|
89
128
|
To enable GA4 call event tracking, CallForge needs the GA4 `client_id` for the visitor (from the `_ga` cookie).
|
|
90
129
|
Optionally provide your GA4 Measurement ID to improve client ID capture reliability when Google Analytics loads late.
|
|
@@ -114,7 +153,7 @@ client.setParams({
|
|
|
114
153
|
});
|
|
115
154
|
```
|
|
116
155
|
|
|
117
|
-
###
|
|
156
|
+
### 6. Track conversion parameters (optional)
|
|
118
157
|
|
|
119
158
|
The client automatically captures ad platform click IDs from the URL:
|
|
120
159
|
|
|
@@ -214,6 +253,41 @@ const intent = await client.createCallIntent();
|
|
|
214
253
|
console.log(intent.callIntentToken);
|
|
215
254
|
```
|
|
216
255
|
|
|
256
|
+
### `client.linkPhoneCall(input)`
|
|
257
|
+
|
|
258
|
+
Create a short-lived realtime call-link intent keyed by dialed number.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
const result = await client.linkPhoneCall({
|
|
262
|
+
phoneNumber: '+13105551234',
|
|
263
|
+
ttlSeconds: 30, // Optional, default 30s
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
console.log(result.status); // 'ready'
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Use this right before `tel:` navigation so inbound call handling can perform strict 1:1 consume.
|
|
270
|
+
|
|
271
|
+
### `client.setWebZip(zipCode, options?)`
|
|
272
|
+
|
|
273
|
+
Store visitor-selected ZIP in the realtime profile layer for immediate call-side enrichment.
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
const result = await client.setWebZip('30309', {
|
|
277
|
+
source: 'manual', // or 'suggested'
|
|
278
|
+
ttlSeconds: 3600, // Optional
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
if (result.status === 'ready') {
|
|
282
|
+
console.log(result.profile.webZipCode);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Behavior:
|
|
287
|
+
- Rejects invalid ZIP values unless they are 5 digits.
|
|
288
|
+
- Writes profile data keyed by `sessionId`.
|
|
289
|
+
- Also mirrors `webZip` and `webZipSource` into queued params for subsequent session refreshes.
|
|
290
|
+
|
|
217
291
|
### `client.onReady(callback)`
|
|
218
292
|
|
|
219
293
|
Subscribe to session ready event. Callback is called once session data is available.
|
|
@@ -325,6 +399,9 @@ import type {
|
|
|
325
399
|
ReadyCallback,
|
|
326
400
|
LocationReadyCallback,
|
|
327
401
|
CallIntentResponse,
|
|
402
|
+
CallLinkIntentResponse,
|
|
403
|
+
RealtimeProfileResponse,
|
|
404
|
+
RealtimeProfileSource,
|
|
328
405
|
} from '@callforge/tracking-client';
|
|
329
406
|
```
|
|
330
407
|
|
package/dist/index.d.mts
CHANGED
|
@@ -83,6 +83,27 @@ interface CallIntentResponse {
|
|
|
83
83
|
expiresAt: string;
|
|
84
84
|
attributionVersion: 'v1';
|
|
85
85
|
}
|
|
86
|
+
interface CallLinkIntentResponse {
|
|
87
|
+
status: 'ready';
|
|
88
|
+
intentId: string;
|
|
89
|
+
sessionId: string;
|
|
90
|
+
categoryId: string;
|
|
91
|
+
phoneNumber: string;
|
|
92
|
+
expiresAt: string;
|
|
93
|
+
}
|
|
94
|
+
type RealtimeProfileSource = 'manual' | 'suggested';
|
|
95
|
+
type RealtimeProfileResponse = {
|
|
96
|
+
status: 'ready';
|
|
97
|
+
profile: {
|
|
98
|
+
sessionId: string;
|
|
99
|
+
webZipCode: string;
|
|
100
|
+
webZipSource: RealtimeProfileSource;
|
|
101
|
+
webZipUpdatedAt: string;
|
|
102
|
+
expiresAt: string;
|
|
103
|
+
};
|
|
104
|
+
} | {
|
|
105
|
+
status: 'unavailable';
|
|
106
|
+
};
|
|
86
107
|
/**
|
|
87
108
|
* Callback function for onReady subscription.
|
|
88
109
|
*/
|
|
@@ -135,6 +156,21 @@ declare class CallForge {
|
|
|
135
156
|
* Create a short-lived call intent token for click/callback deterministic attribution.
|
|
136
157
|
*/
|
|
137
158
|
createCallIntent(): Promise<CallIntentResponse>;
|
|
159
|
+
/**
|
|
160
|
+
* Create a short-lived realtime call-link intent for a specific dialed number.
|
|
161
|
+
* Use this immediately before opening a `tel:` link.
|
|
162
|
+
*/
|
|
163
|
+
linkPhoneCall(input: {
|
|
164
|
+
phoneNumber: string;
|
|
165
|
+
ttlSeconds?: number;
|
|
166
|
+
}): Promise<CallLinkIntentResponse>;
|
|
167
|
+
/**
|
|
168
|
+
* Write visitor-selected web ZIP to the realtime data layer.
|
|
169
|
+
*/
|
|
170
|
+
setWebZip(zipCode: string, options?: {
|
|
171
|
+
source?: RealtimeProfileSource;
|
|
172
|
+
ttlSeconds?: number;
|
|
173
|
+
}): Promise<RealtimeProfileResponse>;
|
|
138
174
|
/**
|
|
139
175
|
* Subscribe to session ready event.
|
|
140
176
|
* Callback is called once session data is available.
|
|
@@ -198,4 +234,4 @@ declare class CallForge {
|
|
|
198
234
|
*/
|
|
199
235
|
declare function getPreloadSnippet(config: CallForgeConfig): string;
|
|
200
236
|
|
|
201
|
-
export { CallForge, type CallForgeConfig, type CallIntentResponse, type LocationReadyCallback, type ReadyCallback, type TrackingLocation, type TrackingLocationSource, type TrackingParams, type TrackingSession, getPreloadSnippet };
|
|
237
|
+
export { CallForge, type CallForgeConfig, type CallIntentResponse, type CallLinkIntentResponse, type LocationReadyCallback, type ReadyCallback, type RealtimeProfileResponse, type RealtimeProfileSource, type TrackingLocation, type TrackingLocationSource, type TrackingParams, type TrackingSession, getPreloadSnippet };
|
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,27 @@ interface CallIntentResponse {
|
|
|
83
83
|
expiresAt: string;
|
|
84
84
|
attributionVersion: 'v1';
|
|
85
85
|
}
|
|
86
|
+
interface CallLinkIntentResponse {
|
|
87
|
+
status: 'ready';
|
|
88
|
+
intentId: string;
|
|
89
|
+
sessionId: string;
|
|
90
|
+
categoryId: string;
|
|
91
|
+
phoneNumber: string;
|
|
92
|
+
expiresAt: string;
|
|
93
|
+
}
|
|
94
|
+
type RealtimeProfileSource = 'manual' | 'suggested';
|
|
95
|
+
type RealtimeProfileResponse = {
|
|
96
|
+
status: 'ready';
|
|
97
|
+
profile: {
|
|
98
|
+
sessionId: string;
|
|
99
|
+
webZipCode: string;
|
|
100
|
+
webZipSource: RealtimeProfileSource;
|
|
101
|
+
webZipUpdatedAt: string;
|
|
102
|
+
expiresAt: string;
|
|
103
|
+
};
|
|
104
|
+
} | {
|
|
105
|
+
status: 'unavailable';
|
|
106
|
+
};
|
|
86
107
|
/**
|
|
87
108
|
* Callback function for onReady subscription.
|
|
88
109
|
*/
|
|
@@ -135,6 +156,21 @@ declare class CallForge {
|
|
|
135
156
|
* Create a short-lived call intent token for click/callback deterministic attribution.
|
|
136
157
|
*/
|
|
137
158
|
createCallIntent(): Promise<CallIntentResponse>;
|
|
159
|
+
/**
|
|
160
|
+
* Create a short-lived realtime call-link intent for a specific dialed number.
|
|
161
|
+
* Use this immediately before opening a `tel:` link.
|
|
162
|
+
*/
|
|
163
|
+
linkPhoneCall(input: {
|
|
164
|
+
phoneNumber: string;
|
|
165
|
+
ttlSeconds?: number;
|
|
166
|
+
}): Promise<CallLinkIntentResponse>;
|
|
167
|
+
/**
|
|
168
|
+
* Write visitor-selected web ZIP to the realtime data layer.
|
|
169
|
+
*/
|
|
170
|
+
setWebZip(zipCode: string, options?: {
|
|
171
|
+
source?: RealtimeProfileSource;
|
|
172
|
+
ttlSeconds?: number;
|
|
173
|
+
}): Promise<RealtimeProfileResponse>;
|
|
138
174
|
/**
|
|
139
175
|
* Subscribe to session ready event.
|
|
140
176
|
* Callback is called once session data is available.
|
|
@@ -198,4 +234,4 @@ declare class CallForge {
|
|
|
198
234
|
*/
|
|
199
235
|
declare function getPreloadSnippet(config: CallForgeConfig): string;
|
|
200
236
|
|
|
201
|
-
export { CallForge, type CallForgeConfig, type CallIntentResponse, type LocationReadyCallback, type ReadyCallback, type TrackingLocation, type TrackingLocationSource, type TrackingParams, type TrackingSession, getPreloadSnippet };
|
|
237
|
+
export { CallForge, type CallForgeConfig, type CallIntentResponse, type CallLinkIntentResponse, type LocationReadyCallback, type ReadyCallback, type RealtimeProfileResponse, type RealtimeProfileSource, type TrackingLocation, type TrackingLocationSource, type TrackingParams, type TrackingSession, getPreloadSnippet };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
7
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
@@ -17,6 +19,7 @@ var __spreadValues = (a, b) => {
|
|
|
17
19
|
}
|
|
18
20
|
return a;
|
|
19
21
|
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
23
|
var __export = (target, all) => {
|
|
21
24
|
for (var name in all)
|
|
22
25
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -203,8 +206,11 @@ var LocationCache = class {
|
|
|
203
206
|
var DEFAULT_ENDPOINT = "https://tracking.callforge.io";
|
|
204
207
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
205
208
|
var CALL_INTENT_TIMEOUT_MS = 8e3;
|
|
209
|
+
var REALTIME_CALL_LINK_TIMEOUT_MS = 5e3;
|
|
210
|
+
var REALTIME_PROFILE_TIMEOUT_MS = 5e3;
|
|
206
211
|
var BOOTSTRAP_TOKEN_EXPIRY_BUFFER_MS = 1e4;
|
|
207
212
|
var AUTO_PARAMS = ["gclid", "gbraid", "wbraid", "msclkid", "fbclid", "gad_campaignid", "gad_source"];
|
|
213
|
+
var ZIP_CODE_PATTERN = /^\d{5}$/;
|
|
208
214
|
var CallForge = class _CallForge {
|
|
209
215
|
constructor(config) {
|
|
210
216
|
this.bootstrapMemoryCache = null;
|
|
@@ -289,6 +295,77 @@ var CallForge = class _CallForge {
|
|
|
289
295
|
clearTimeout(timeoutId);
|
|
290
296
|
}
|
|
291
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Create a short-lived realtime call-link intent for a specific dialed number.
|
|
300
|
+
* Use this immediately before opening a `tel:` link.
|
|
301
|
+
*/
|
|
302
|
+
async linkPhoneCall(input) {
|
|
303
|
+
const session = await this.getSession();
|
|
304
|
+
const controller = new AbortController();
|
|
305
|
+
const timeoutId = setTimeout(() => controller.abort(), REALTIME_CALL_LINK_TIMEOUT_MS);
|
|
306
|
+
try {
|
|
307
|
+
const response = await fetch(`${this.config.endpoint}/v1/tracking/call-link-intent`, {
|
|
308
|
+
method: "POST",
|
|
309
|
+
headers: {
|
|
310
|
+
"Content-Type": "application/json"
|
|
311
|
+
},
|
|
312
|
+
credentials: "omit",
|
|
313
|
+
signal: controller.signal,
|
|
314
|
+
body: JSON.stringify({
|
|
315
|
+
sessionToken: session.sessionToken,
|
|
316
|
+
phoneNumber: input.phoneNumber,
|
|
317
|
+
ttlSeconds: input.ttlSeconds
|
|
318
|
+
})
|
|
319
|
+
});
|
|
320
|
+
if (!response.ok) {
|
|
321
|
+
throw new Error(`Realtime call-link API error: ${response.status} ${response.statusText}`);
|
|
322
|
+
}
|
|
323
|
+
return await response.json();
|
|
324
|
+
} finally {
|
|
325
|
+
clearTimeout(timeoutId);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Write visitor-selected web ZIP to the realtime data layer.
|
|
330
|
+
*/
|
|
331
|
+
async setWebZip(zipCode, options) {
|
|
332
|
+
const normalizedZip = zipCode.trim();
|
|
333
|
+
if (!ZIP_CODE_PATTERN.test(normalizedZip)) {
|
|
334
|
+
throw new Error("Invalid ZIP code. Expected a 5-digit ZIP.");
|
|
335
|
+
}
|
|
336
|
+
const session = await this.getSession();
|
|
337
|
+
const controller = new AbortController();
|
|
338
|
+
const timeoutId = setTimeout(() => controller.abort(), REALTIME_PROFILE_TIMEOUT_MS);
|
|
339
|
+
try {
|
|
340
|
+
const response = await fetch(`${this.config.endpoint}/v1/tracking/realtime-profile`, {
|
|
341
|
+
method: "POST",
|
|
342
|
+
headers: {
|
|
343
|
+
"Content-Type": "application/json"
|
|
344
|
+
},
|
|
345
|
+
credentials: "omit",
|
|
346
|
+
signal: controller.signal,
|
|
347
|
+
body: JSON.stringify({
|
|
348
|
+
sessionToken: session.sessionToken,
|
|
349
|
+
webZip: normalizedZip,
|
|
350
|
+
source: options == null ? void 0 : options.source,
|
|
351
|
+
ttlSeconds: options == null ? void 0 : options.ttlSeconds
|
|
352
|
+
})
|
|
353
|
+
});
|
|
354
|
+
if (!response.ok) {
|
|
355
|
+
throw new Error(`Realtime profile API error: ${response.status} ${response.statusText}`);
|
|
356
|
+
}
|
|
357
|
+
const result = await response.json();
|
|
358
|
+
if (result.status === "ready") {
|
|
359
|
+
this.customParams = __spreadProps(__spreadValues({}, this.customParams), {
|
|
360
|
+
webZip: result.profile.webZipCode,
|
|
361
|
+
webZipSource: result.profile.webZipSource
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
365
|
+
} finally {
|
|
366
|
+
clearTimeout(timeoutId);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
292
369
|
/**
|
|
293
370
|
* Subscribe to session ready event.
|
|
294
371
|
* Callback is called once session data is available.
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +16,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
16
|
}
|
|
15
17
|
return a;
|
|
16
18
|
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
17
20
|
|
|
18
21
|
// src/cache.ts
|
|
19
22
|
var EXPIRY_BUFFER_MS = 3e4;
|
|
@@ -179,8 +182,11 @@ var LocationCache = class {
|
|
|
179
182
|
var DEFAULT_ENDPOINT = "https://tracking.callforge.io";
|
|
180
183
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
181
184
|
var CALL_INTENT_TIMEOUT_MS = 8e3;
|
|
185
|
+
var REALTIME_CALL_LINK_TIMEOUT_MS = 5e3;
|
|
186
|
+
var REALTIME_PROFILE_TIMEOUT_MS = 5e3;
|
|
182
187
|
var BOOTSTRAP_TOKEN_EXPIRY_BUFFER_MS = 1e4;
|
|
183
188
|
var AUTO_PARAMS = ["gclid", "gbraid", "wbraid", "msclkid", "fbclid", "gad_campaignid", "gad_source"];
|
|
189
|
+
var ZIP_CODE_PATTERN = /^\d{5}$/;
|
|
184
190
|
var CallForge = class _CallForge {
|
|
185
191
|
constructor(config) {
|
|
186
192
|
this.bootstrapMemoryCache = null;
|
|
@@ -265,6 +271,77 @@ var CallForge = class _CallForge {
|
|
|
265
271
|
clearTimeout(timeoutId);
|
|
266
272
|
}
|
|
267
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* Create a short-lived realtime call-link intent for a specific dialed number.
|
|
276
|
+
* Use this immediately before opening a `tel:` link.
|
|
277
|
+
*/
|
|
278
|
+
async linkPhoneCall(input) {
|
|
279
|
+
const session = await this.getSession();
|
|
280
|
+
const controller = new AbortController();
|
|
281
|
+
const timeoutId = setTimeout(() => controller.abort(), REALTIME_CALL_LINK_TIMEOUT_MS);
|
|
282
|
+
try {
|
|
283
|
+
const response = await fetch(`${this.config.endpoint}/v1/tracking/call-link-intent`, {
|
|
284
|
+
method: "POST",
|
|
285
|
+
headers: {
|
|
286
|
+
"Content-Type": "application/json"
|
|
287
|
+
},
|
|
288
|
+
credentials: "omit",
|
|
289
|
+
signal: controller.signal,
|
|
290
|
+
body: JSON.stringify({
|
|
291
|
+
sessionToken: session.sessionToken,
|
|
292
|
+
phoneNumber: input.phoneNumber,
|
|
293
|
+
ttlSeconds: input.ttlSeconds
|
|
294
|
+
})
|
|
295
|
+
});
|
|
296
|
+
if (!response.ok) {
|
|
297
|
+
throw new Error(`Realtime call-link API error: ${response.status} ${response.statusText}`);
|
|
298
|
+
}
|
|
299
|
+
return await response.json();
|
|
300
|
+
} finally {
|
|
301
|
+
clearTimeout(timeoutId);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Write visitor-selected web ZIP to the realtime data layer.
|
|
306
|
+
*/
|
|
307
|
+
async setWebZip(zipCode, options) {
|
|
308
|
+
const normalizedZip = zipCode.trim();
|
|
309
|
+
if (!ZIP_CODE_PATTERN.test(normalizedZip)) {
|
|
310
|
+
throw new Error("Invalid ZIP code. Expected a 5-digit ZIP.");
|
|
311
|
+
}
|
|
312
|
+
const session = await this.getSession();
|
|
313
|
+
const controller = new AbortController();
|
|
314
|
+
const timeoutId = setTimeout(() => controller.abort(), REALTIME_PROFILE_TIMEOUT_MS);
|
|
315
|
+
try {
|
|
316
|
+
const response = await fetch(`${this.config.endpoint}/v1/tracking/realtime-profile`, {
|
|
317
|
+
method: "POST",
|
|
318
|
+
headers: {
|
|
319
|
+
"Content-Type": "application/json"
|
|
320
|
+
},
|
|
321
|
+
credentials: "omit",
|
|
322
|
+
signal: controller.signal,
|
|
323
|
+
body: JSON.stringify({
|
|
324
|
+
sessionToken: session.sessionToken,
|
|
325
|
+
webZip: normalizedZip,
|
|
326
|
+
source: options == null ? void 0 : options.source,
|
|
327
|
+
ttlSeconds: options == null ? void 0 : options.ttlSeconds
|
|
328
|
+
})
|
|
329
|
+
});
|
|
330
|
+
if (!response.ok) {
|
|
331
|
+
throw new Error(`Realtime profile API error: ${response.status} ${response.statusText}`);
|
|
332
|
+
}
|
|
333
|
+
const result = await response.json();
|
|
334
|
+
if (result.status === "ready") {
|
|
335
|
+
this.customParams = __spreadProps(__spreadValues({}, this.customParams), {
|
|
336
|
+
webZip: result.profile.webZipCode,
|
|
337
|
+
webZipSource: result.profile.webZipSource
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
return result;
|
|
341
|
+
} finally {
|
|
342
|
+
clearTimeout(timeoutId);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
268
345
|
/**
|
|
269
346
|
* Subscribe to session ready event.
|
|
270
347
|
* Callback is called once session data is available.
|