@tolinku/web-sdk 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sitepact LLC (Tolinku)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # @tolinku/web-sdk
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@tolinku/web-sdk.svg)](https://www.npmjs.com/package/@tolinku/web-sdk)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
+
6
+ The official [Tolinku](https://tolinku.com) SDK for the web. Add deep linking, analytics, referral tracking, deferred deep links, smart banners, and in-app messages to any website or web app.
7
+
8
+ ## What is Tolinku?
9
+
10
+ [Tolinku](https://tolinku.com) is a deep linking platform for mobile and web apps. It handles Universal Links (iOS), App Links (Android), deferred deep linking, referral programs, analytics, and smart banners. Tolinku provides a complete toolkit for user acquisition, attribution, and engagement across platforms.
11
+
12
+ Get your API key at [tolinku.com](https://tolinku.com) and check out the [documentation](https://tolinku.com/docs) to get started.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @tolinku/web-sdk
18
+ ```
19
+
20
+ Or with yarn:
21
+
22
+ ```bash
23
+ yarn add @tolinku/web-sdk
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```typescript
29
+ import { Tolinku } from '@tolinku/web-sdk';
30
+
31
+ const tolinku = new Tolinku({ apiKey: 'tolk_pub_your_api_key' });
32
+
33
+ // Identify a user
34
+ tolinku.setUserId('user_123');
35
+
36
+ // Track a custom event
37
+ await tolinku.track('purchase', { plan: 'growth' });
38
+ ```
39
+
40
+ ## Features
41
+
42
+ ### Analytics
43
+
44
+ Track custom events with automatic batching (events are queued and sent in batches of 10, or every 5 seconds). On page unload, remaining events are delivered via `navigator.sendBeacon` for reliable delivery.
45
+
46
+ ```typescript
47
+ await tolinku.track('signup_completed', { source: 'landing_page' });
48
+
49
+ // Flush queued events immediately
50
+ await tolinku.flush();
51
+ ```
52
+
53
+ ### Referrals
54
+
55
+ Create and manage referral programs with built-in leaderboards and reward tracking.
56
+
57
+ ```typescript
58
+ // Create a referral
59
+ const { referral_code, referral_url } = await tolinku.referrals.create({
60
+ userId: 'user_123',
61
+ userName: 'Alice',
62
+ });
63
+
64
+ // Look up a referral
65
+ const info = await tolinku.referrals.get(referral_code);
66
+
67
+ // Complete a referral (when a referred user converts)
68
+ await tolinku.referrals.complete({
69
+ code: referral_code,
70
+ referredUserId: 'user_456',
71
+ referredUserName: 'Bob',
72
+ });
73
+
74
+ // Update milestone
75
+ await tolinku.referrals.milestone({
76
+ code: referral_code,
77
+ milestone: 'first_purchase',
78
+ });
79
+
80
+ // Claim reward
81
+ await tolinku.referrals.claimReward(referral_code);
82
+
83
+ // Fetch leaderboard
84
+ const { leaderboard } = await tolinku.referrals.leaderboard(10);
85
+ ```
86
+
87
+ ### Deferred Deep Links
88
+
89
+ Recover deep link context for users who installed your app after clicking a link. Deferred deep linking lets you route users to specific content even when the app was not installed at the time of the click.
90
+
91
+ ```typescript
92
+ // Claim by referrer token (from Play Store referrer or clipboard)
93
+ const link = await tolinku.deferred.claimByToken('abc123');
94
+ if (link) {
95
+ console.log(link.deep_link_path); // e.g. "/merchant/xyz"
96
+ }
97
+
98
+ // Claim by device signal matching
99
+ const link = await tolinku.deferred.claimBySignals({
100
+ appspaceId: 'your_appspace_id',
101
+ });
102
+ ```
103
+
104
+ ### In-App Messages
105
+
106
+ Display visually rich, server-configured messages as modal overlays. Create and manage messages from the Tolinku dashboard without shipping app updates.
107
+
108
+ ```typescript
109
+ // Show the highest-priority message matching a trigger
110
+ await tolinku.showMessage({ trigger: 'milestone' });
111
+
112
+ // Dismiss the current message
113
+ tolinku.dismissMessage();
114
+ ```
115
+
116
+ Messages support components including headings, text blocks, images, buttons, sections, spacers, and dividers. Impression tracking and suppression rules (max impressions, minimum interval, dismiss duration) are handled automatically.
117
+
118
+ ### Smart Banners
119
+
120
+ Display app install banners that link users to the App Store, Google Play, or a custom URL. Smart banners help convert web visitors into app users with a non-intrusive prompt.
121
+
122
+ ```typescript
123
+ // Show a smart banner
124
+ await tolinku.showBanner({ position: 'top' });
125
+
126
+ // Dismiss the banner
127
+ tolinku.dismissBanner();
128
+ ```
129
+
130
+ Banners include an app icon, title, body text, and a call-to-action button. Dismissal state is tracked so banners do not reappear until the configured duration has passed.
131
+
132
+ ## Configuration Options
133
+
134
+ ```typescript
135
+ const tolinku = new Tolinku({
136
+ apiKey: 'tolk_pub_your_api_key', // Required. Your Tolinku publishable API key.
137
+ baseUrl: 'https://api.tolinku.com', // Optional. API base URL.
138
+ });
139
+
140
+ // Set user identity at any time
141
+ tolinku.setUserId('user_123');
142
+ ```
143
+
144
+ ## API Reference
145
+
146
+ ### `Tolinku`
147
+
148
+ | Method | Description |
149
+ |--------|-------------|
150
+ | `new Tolinku(config)` | Create a new SDK instance |
151
+ | `setUserId(userId)` | Set or clear the current user ID |
152
+ | `track(eventType, properties?)` | Track a custom event |
153
+ | `flush()` | Flush queued analytics events |
154
+ | `showBanner(options?)` | Display a smart banner |
155
+ | `dismissBanner()` | Dismiss the smart banner |
156
+ | `showMessage(options?)` | Show an in-app message |
157
+ | `dismissMessage()` | Dismiss the in-app message |
158
+ | `destroy()` | Clean up all resources |
159
+
160
+ ### `tolinku.analytics`
161
+
162
+ | Method | Description |
163
+ |--------|-------------|
164
+ | `track(eventType, properties?)` | Queue a custom event |
165
+ | `flush()` | Send all queued events |
166
+
167
+ ### `tolinku.referrals`
168
+
169
+ | Method | Description |
170
+ |--------|-------------|
171
+ | `create(options)` | Create a new referral |
172
+ | `get(code)` | Get referral details by code |
173
+ | `complete(options)` | Mark a referral as converted |
174
+ | `milestone(options)` | Update a referral milestone |
175
+ | `claimReward(code)` | Claim a referral reward |
176
+ | `leaderboard(limit?)` | Fetch the referral leaderboard |
177
+
178
+ ### `tolinku.deferred`
179
+
180
+ | Method | Description |
181
+ |--------|-------------|
182
+ | `claimByToken(token)` | Claim a deferred link by token |
183
+ | `claimBySignals(options)` | Claim a deferred link by device signals |
184
+
185
+ ## Documentation
186
+
187
+ Full documentation is available at [tolinku.com/docs](https://tolinku.com/docs).
188
+
189
+ ## Community
190
+
191
+ - [GitHub](https://github.com/tolinku)
192
+ - [X (Twitter)](https://x.com/trytolinku)
193
+ - [Facebook](https://facebook.com/trytolinku)
194
+ - [Instagram](https://www.instagram.com/trytolinku/)
195
+
196
+ ## License
197
+
198
+ MIT
@@ -0,0 +1,298 @@
1
+ /** Configuration options for the Tolinku SDK */
2
+ interface TolinkuConfig {
3
+ /** Your Tolinku publishable API key (starts with tolk_pub_) */
4
+ apiKey: string;
5
+ /** Base URL of your Tolinku domain. Defaults to https://api.tolinku.com */
6
+ baseUrl?: string;
7
+ }
8
+ /** Properties for custom event tracking */
9
+ interface TrackProperties {
10
+ campaign?: string;
11
+ source?: string;
12
+ medium?: string;
13
+ platform?: string;
14
+ [key: string]: string | undefined;
15
+ }
16
+ /** Options for creating a referral */
17
+ interface CreateReferralOptions {
18
+ userId: string;
19
+ metadata?: Record<string, string>;
20
+ userName?: string;
21
+ }
22
+ /** Response from creating a referral */
23
+ interface CreateReferralResult {
24
+ referral_code: string;
25
+ referral_url: string | null;
26
+ referral_id: string;
27
+ }
28
+ /** Options for completing a referral */
29
+ interface CompleteReferralOptions {
30
+ code: string;
31
+ referredUserId: string;
32
+ milestone?: string;
33
+ referredUserName?: string;
34
+ }
35
+ /** Response from completing a referral */
36
+ interface CompleteReferralResult {
37
+ referral: {
38
+ id: string;
39
+ referrer_id: string;
40
+ referred_user_id: string;
41
+ status: string;
42
+ milestone: string;
43
+ completed_at: string;
44
+ reward_type: string | null;
45
+ reward_value: string | null;
46
+ };
47
+ }
48
+ /** Options for updating a referral milestone */
49
+ interface MilestoneOptions {
50
+ code: string;
51
+ milestone: string;
52
+ }
53
+ /** Response from updating a milestone */
54
+ interface MilestoneResult {
55
+ referral: {
56
+ id: string;
57
+ referral_code: string;
58
+ milestone: string;
59
+ status: string;
60
+ reward_type: string | null;
61
+ reward_value: string | null;
62
+ };
63
+ }
64
+ /** Referral info returned by GET /api/referral/:code */
65
+ interface ReferralInfo {
66
+ referrer_id: string;
67
+ status: string;
68
+ milestone: string;
69
+ milestone_history: Array<{
70
+ milestone: string;
71
+ timestamp: string;
72
+ }>;
73
+ reward_type: string | null;
74
+ reward_value: string | null;
75
+ reward_claimed: boolean;
76
+ created_at: string;
77
+ }
78
+ /** Leaderboard entry */
79
+ interface LeaderboardEntry {
80
+ referrer_id: string;
81
+ referrer_name: string | null;
82
+ total: number;
83
+ completed: number;
84
+ pending: number;
85
+ total_reward_value: string | null;
86
+ }
87
+ /** Deferred deep link result */
88
+ interface DeferredLink {
89
+ deep_link_path: string;
90
+ appspace_id: string;
91
+ referrer_id?: string;
92
+ referral_code?: string;
93
+ }
94
+ /** Options for claiming deferred link by signals */
95
+ interface ClaimBySignalsOptions {
96
+ appspaceId: string;
97
+ timezone?: string;
98
+ language?: string;
99
+ screenWidth?: number;
100
+ screenHeight?: number;
101
+ }
102
+ /** Banner config returned by the API */
103
+ interface BannerConfig {
104
+ enabled: boolean;
105
+ app_name?: string;
106
+ app_icon?: string;
107
+ install_url?: string;
108
+ banners: BannerItem[];
109
+ }
110
+ /** Individual banner item */
111
+ interface BannerItem {
112
+ id: string;
113
+ label: string;
114
+ title: string;
115
+ body: string | null;
116
+ action_url: string | null;
117
+ background_color: string;
118
+ text_color: string;
119
+ cta_text: string | null;
120
+ position: string | null;
121
+ dismiss_days: number | null;
122
+ priority: number;
123
+ }
124
+ /** Options for showing a banner */
125
+ interface ShowBannerOptions {
126
+ position?: 'top' | 'bottom';
127
+ label?: string;
128
+ }
129
+ /** In-app message from the API */
130
+ interface Message {
131
+ id: string;
132
+ name: string;
133
+ title: string;
134
+ body: string | null;
135
+ trigger: string;
136
+ trigger_value: string | null;
137
+ content: MessageContent | null;
138
+ background_color: string;
139
+ priority: number;
140
+ dismiss_days: number | null;
141
+ max_impressions: number | null;
142
+ min_interval_hours: number | null;
143
+ }
144
+ /** Puck component content tree */
145
+ interface MessageContent {
146
+ root: {
147
+ props: Record<string, unknown>;
148
+ };
149
+ content: MessageComponent[];
150
+ }
151
+ /** A single Puck component */
152
+ interface MessageComponent {
153
+ type: string;
154
+ props: Record<string, unknown>;
155
+ }
156
+ /** Options for showing an in-app message */
157
+ interface ShowMessageOptions {
158
+ trigger?: string;
159
+ triggerValue?: string;
160
+ onDismiss?: (messageId: string) => void;
161
+ onButtonPress?: (action: string, messageId: string) => void;
162
+ }
163
+
164
+ declare class HttpClient {
165
+ private _baseUrl;
166
+ private apiKey;
167
+ private abortController;
168
+ constructor(config: Required<TolinkuConfig>);
169
+ /** Abort all in-flight requests (called by Tolinku.destroy()) */
170
+ abort(): void;
171
+ /** Get a signal for the current request batch, creating a controller if needed */
172
+ private get signal();
173
+ /** Public accessor for the base URL */
174
+ get baseUrl(): string;
175
+ /** Public accessor for the API key (used by sendBeacon which cannot set custom headers) */
176
+ get key(): string;
177
+ get<T>(path: string, params?: Record<string, string>): Promise<T>;
178
+ post<T>(path: string, body?: Record<string, unknown>): Promise<T>;
179
+ /** GET without API key auth (for public endpoints like banner config) */
180
+ getPublic<T>(path: string, params?: Record<string, string>): Promise<T>;
181
+ /** POST without API key auth (for public endpoints like deferred claim) */
182
+ postPublic<T>(path: string, body?: Record<string, unknown>): Promise<T>;
183
+ /**
184
+ * Fetch with retry logic. Retries on network errors, HTTP 429, and 5xx responses.
185
+ * Uses exponential backoff: BASE_DELAY_MS * 2^attempt + random jitter.
186
+ * Respects Retry-After header on 429 responses.
187
+ * Does NOT retry on 4xx errors (except 429) or successful responses.
188
+ */
189
+ private fetchWithRetry;
190
+ /** Compute backoff delay: BASE_DELAY_MS * 2^attempt + random jitter (0 to MAX_JITTER_MS) */
191
+ private computeDelay;
192
+ /** Sleep for a given duration, but throw if the signal is aborted */
193
+ private sleep;
194
+ /** Safely parse JSON from a response, handling non-JSON 200s */
195
+ private parseJson;
196
+ private headers;
197
+ }
198
+ declare class TolinkuError extends Error {
199
+ status: number;
200
+ code: string | undefined;
201
+ constructor(message: string, status: number, code?: string);
202
+ }
203
+
204
+ declare class Analytics {
205
+ private client;
206
+ private queue;
207
+ private flushTimer;
208
+ private unloadHandler;
209
+ constructor(client: HttpClient);
210
+ /**
211
+ * Track a custom event. Event type must start with "custom." and match
212
+ * the pattern custom.[a-z0-9_]+
213
+ *
214
+ * Events are queued and sent in batches for efficiency.
215
+ */
216
+ track(eventType: string, properties?: TrackProperties): Promise<void>;
217
+ /** Send all queued events to the server */
218
+ flush(): Promise<void>;
219
+ /**
220
+ * Flush remaining events using navigator.sendBeacon (best-effort).
221
+ * Called on page unload when a normal fetch may not complete.
222
+ */
223
+ private flushBeacon;
224
+ /** Clean up timers and event listeners. Called by Tolinku.destroy(). */
225
+ destroy(): void;
226
+ }
227
+
228
+ declare class Referrals {
229
+ private client;
230
+ constructor(client: HttpClient);
231
+ /** Create a new referral for a user */
232
+ create(options: CreateReferralOptions): Promise<CreateReferralResult>;
233
+ /** Get referral info by code */
234
+ get(code: string): Promise<ReferralInfo>;
235
+ /** Complete a referral (mark as converted) */
236
+ complete(options: CompleteReferralOptions): Promise<CompleteReferralResult>;
237
+ /** Update a referral milestone */
238
+ milestone(options: MilestoneOptions): Promise<MilestoneResult>;
239
+ /** Claim a referral reward */
240
+ claimReward(code: string): Promise<{
241
+ success: boolean;
242
+ referral_code: string;
243
+ reward_claimed: boolean;
244
+ }>;
245
+ /** Get the referral leaderboard */
246
+ leaderboard(limit?: number): Promise<{
247
+ leaderboard: LeaderboardEntry[];
248
+ }>;
249
+ }
250
+
251
+ declare class Deferred {
252
+ private client;
253
+ constructor(client: HttpClient);
254
+ /** Claim a deferred deep link by referrer token (from Play Store referrer or clipboard) */
255
+ claimByToken(token: string): Promise<DeferredLink | null>;
256
+ /** Claim a deferred deep link by device signal matching */
257
+ claimBySignals(options: ClaimBySignalsOptions): Promise<DeferredLink | null>;
258
+ }
259
+
260
+ declare class Tolinku {
261
+ private client;
262
+ /** Analytics: track custom events */
263
+ readonly analytics: Analytics;
264
+ /** Referrals: create, complete, milestone, leaderboard */
265
+ readonly referrals: Referrals;
266
+ /** Deferred deep links: claim by token or signals */
267
+ readonly deferred: Deferred;
268
+ private banners;
269
+ private messages;
270
+ /** The current user ID, used for segment targeting and analytics. */
271
+ private _userId;
272
+ constructor(config: TolinkuConfig);
273
+ /**
274
+ * Set the user ID for segment targeting and analytics attribution.
275
+ * Pass null to clear the user ID.
276
+ */
277
+ setUserId(userId: string | null): void;
278
+ /**
279
+ * Track a custom event (shorthand for analytics.track).
280
+ * Event type is auto-prefixed with "custom." if not already.
281
+ * If a userId has been set, it is automatically injected into event properties.
282
+ */
283
+ track(eventType: string, properties?: TrackProperties): Promise<void>;
284
+ /** Show a smart banner at the top or bottom of the page */
285
+ showBanner(options?: ShowBannerOptions): Promise<void>;
286
+ /** Dismiss the currently visible smart banner */
287
+ dismissBanner(): void;
288
+ /** Show an in-app message as a modal overlay */
289
+ showMessage(options?: ShowMessageOptions): Promise<void>;
290
+ /** Dismiss the currently visible in-app message */
291
+ dismissMessage(): void;
292
+ /** Flush any queued analytics events immediately */
293
+ flush(): Promise<void>;
294
+ /** Clean up all DOM elements, flush events, and cancel in-flight requests (e.g. before unmounting in SPAs) */
295
+ destroy(): void;
296
+ }
297
+
298
+ export { type BannerConfig, type BannerItem, type ClaimBySignalsOptions, type CompleteReferralOptions, type CompleteReferralResult, type CreateReferralOptions, type CreateReferralResult, type DeferredLink, type LeaderboardEntry, type Message, type MessageComponent, type MessageContent, type MilestoneOptions, type MilestoneResult, type ReferralInfo, type ShowBannerOptions, type ShowMessageOptions, Tolinku, type TolinkuConfig, TolinkuError, type TrackProperties };