@tolinku/web-sdk 0.3.0 → 0.4.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 +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +61 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -5
- package/dist/index.mjs.map +1 -1
- package/dist/tolinku.min.js +71 -0
- package/dist/tolinku.min.js.map +1 -0
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -167,7 +167,11 @@ var HttpClient = class {
|
|
|
167
167
|
}
|
|
168
168
|
headers() {
|
|
169
169
|
return {
|
|
170
|
-
"X-API-Key": this.apiKey
|
|
170
|
+
"X-API-Key": this.apiKey,
|
|
171
|
+
// Browsers default to "Accept: */*", which a server content-negotiating an
|
|
172
|
+
// error page reads as "HTML is fine". Saying so explicitly keeps an error
|
|
173
|
+
// parseable instead of arriving as a rendered page.
|
|
174
|
+
"Accept": "application/json"
|
|
171
175
|
};
|
|
172
176
|
}
|
|
173
177
|
};
|
|
@@ -525,6 +529,7 @@ var Referrals = class {
|
|
|
525
529
|
};
|
|
526
530
|
|
|
527
531
|
// src/deferred.ts
|
|
532
|
+
var CLAIMED_KEY = "tolinku_deferred_claimed";
|
|
528
533
|
var Deferred = class {
|
|
529
534
|
constructor(client) {
|
|
530
535
|
this.client = client;
|
|
@@ -538,10 +543,60 @@ var Deferred = class {
|
|
|
538
543
|
return null;
|
|
539
544
|
}
|
|
540
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* Recover the link that led here, once.
|
|
548
|
+
*
|
|
549
|
+
* There is no Play Install Referrer on the web, so this is signal matching
|
|
550
|
+
* with the bookkeeping that makes calling it safe. That bookkeeping is the
|
|
551
|
+
* point: a claim is consumed the first time it succeeds, so an app calling
|
|
552
|
+
* claimBySignals on every page load asks again after the answer is already
|
|
553
|
+
* spent, and every one of those asks is recorded as a miss. The match rate on
|
|
554
|
+
* the dashboard then falls towards zero while the integration is working
|
|
555
|
+
* correctly, which is a hard thing to diagnose from the outside.
|
|
556
|
+
*
|
|
557
|
+
* Call it once on first run. Calling it again is free after the first.
|
|
558
|
+
*
|
|
559
|
+
* Named to match the Android, React Native and Flutter SDKs, where the same
|
|
560
|
+
* call also tries the install referrer before falling back to here.
|
|
561
|
+
*/
|
|
562
|
+
async claimDeferredLink(options) {
|
|
563
|
+
if (!options.appspaceId || !options.appspaceId.trim()) {
|
|
564
|
+
throw new Error("Tolinku: appspaceId is required and must not be blank for claimDeferredLink.");
|
|
565
|
+
}
|
|
566
|
+
if (!options.force && this.alreadyAttempted()) return null;
|
|
567
|
+
const { link, settled } = await this.attemptSignals({ appspaceId: options.appspaceId });
|
|
568
|
+
if (settled) this.rememberAttempt();
|
|
569
|
+
return link;
|
|
570
|
+
}
|
|
571
|
+
alreadyAttempted() {
|
|
572
|
+
try {
|
|
573
|
+
return window.localStorage.getItem(CLAIMED_KEY) !== null;
|
|
574
|
+
} catch {
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
rememberAttempt() {
|
|
579
|
+
try {
|
|
580
|
+
window.localStorage.setItem(CLAIMED_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
}
|
|
541
584
|
/** Claim a deferred deep link by device signal matching */
|
|
542
585
|
async claimBySignals(options) {
|
|
586
|
+
return (await this.attemptSignals(options)).link;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* The signal claim, with whether the server actually answered.
|
|
590
|
+
*
|
|
591
|
+
* `settled` separates "nothing is waiting for this device", which no amount
|
|
592
|
+
* of asking will change, from "the request never got there". Both surface as
|
|
593
|
+
* null to callers of claimBySignals, but claimDeferredLink has to tell them
|
|
594
|
+
* apart: recording an attempt that never reached the server would spend an
|
|
595
|
+
* install's one chance at attribution on a dropped connection.
|
|
596
|
+
*/
|
|
597
|
+
async attemptSignals(options) {
|
|
543
598
|
try {
|
|
544
|
-
|
|
599
|
+
const link = await this.client.postPublic("/v1/api/deferred/claim-by-signals", {
|
|
545
600
|
appspace_id: options.appspaceId,
|
|
546
601
|
timezone: options.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
547
602
|
language: options.language || navigator.language,
|
|
@@ -550,10 +605,11 @@ var Deferred = class {
|
|
|
550
605
|
// Separates devices reporting identical logical dimensions.
|
|
551
606
|
device_pixel_ratio: options.devicePixelRatio || window.devicePixelRatio || 1
|
|
552
607
|
});
|
|
608
|
+
return { link, settled: true };
|
|
553
609
|
} catch (err) {
|
|
554
610
|
const status = err?.statusCode ?? err?.status;
|
|
555
611
|
if (status === 404) {
|
|
556
|
-
return null;
|
|
612
|
+
return { link: null, settled: true };
|
|
557
613
|
}
|
|
558
614
|
if (status === 403) {
|
|
559
615
|
console.warn(
|
|
@@ -562,10 +618,10 @@ var Deferred = class {
|
|
|
562
618
|
"under Settings), not your subdomain or slug.",
|
|
563
619
|
err
|
|
564
620
|
);
|
|
565
|
-
return null;
|
|
621
|
+
return { link: null, settled: false };
|
|
566
622
|
}
|
|
567
623
|
console.warn("[Tolinku] Failed to claim deferred link by signals:", err);
|
|
568
|
-
return null;
|
|
624
|
+
return { link: null, settled: false };
|
|
569
625
|
}
|
|
570
626
|
}
|
|
571
627
|
};
|