@returningai/widget-sdk 1.2.13 → 1.2.15
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 +527 -572
- package/dist/rai-widget.iife.js +1 -1
- package/dist/rai-widget.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,572 +1,527 @@
|
|
|
1
|
-
# @returningai/widget-sdk
|
|
2
|
-
|
|
3
|
-
Embed ReturningAI widgets on any website — React, Vue, Angular, or plain `<script>` tag. No external dependencies.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Quick Start
|
|
8
|
-
|
|
9
|
-
### 1. Get your credentials
|
|
10
|
-
|
|
11
|
-
Log in to your **ReturningAI dashboard** and go to **Community Settings > Integrations > SDK Access**. You will find:
|
|
12
|
-
|
|
13
|
-
- **Widget ID** — identifies your widget
|
|
14
|
-
- **API URL** — the base URL for widget authentication
|
|
15
|
-
- **Widget URL** — the URL that loads the widget content
|
|
16
|
-
|
|
17
|
-
### 2. Add the SDK to your page
|
|
18
|
-
|
|
19
|
-
```html
|
|
20
|
-
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
21
|
-
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
22
|
-
data-widget-id="YOUR_WIDGET_ID"
|
|
23
|
-
data-widget-type="store"
|
|
24
|
-
data-theme="dark"
|
|
25
|
-
data-email="user@example.com"
|
|
26
|
-
api-url="YOUR_API_URL"
|
|
27
|
-
widget-url="YOUR_WIDGET_URL"
|
|
28
|
-
></script>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
That's it. The widget will authenticate and render automatically.
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
**Step
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
data-widget-
|
|
140
|
-
data-
|
|
141
|
-
data-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
data-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
data-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
data-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
theme="dark"
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
></rai-
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
widget
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
|
527
|
-
|
|
|
528
|
-
| `rai-mounted` | `{}` | Widget bundle mounted successfully (bundle mode) |
|
|
529
|
-
| `rai-error` | `{ message }` | Auth failed after all retries |
|
|
530
|
-
| `rai-logout` | `{}` | Widget logged out |
|
|
531
|
-
| `rai-height-change` | `{ height }` | iframe resized (after debounce) |
|
|
532
|
-
|
|
533
|
-
```js
|
|
534
|
-
// Script-tag embed
|
|
535
|
-
const widget = document.querySelector('[data-widget-id]')
|
|
536
|
-
|
|
537
|
-
// Custom element embed
|
|
538
|
-
const widget = document.querySelector('rai-store-widget')
|
|
539
|
-
|
|
540
|
-
widget.addEventListener('rai-authenticated', () => { /* auth succeeded */ })
|
|
541
|
-
widget.addEventListener('rai-ready', () => { /* widget loaded and visible (iframe mode) */ })
|
|
542
|
-
widget.addEventListener('rai-mounted', () => { /* widget mounted (bundle mode) */ })
|
|
543
|
-
widget.addEventListener('rai-error', (e) => console.error(e.detail.message))
|
|
544
|
-
widget.addEventListener('rai-logout', () => { /* user logged out */ })
|
|
545
|
-
widget.addEventListener('rai-height-change', (e) => console.log(e.detail.height))
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
---
|
|
549
|
-
|
|
550
|
-
## Public API
|
|
551
|
-
|
|
552
|
-
After the SDK loads, `window.ReturningAIWidget` is available:
|
|
553
|
-
|
|
554
|
-
```js
|
|
555
|
-
window.ReturningAIWidget.version // current SDK version
|
|
556
|
-
await window.ReturningAIWidget.reload() // re-runs auth flow and reloads widget
|
|
557
|
-
await window.ReturningAIWidget.logout() // clears tokens and removes widget
|
|
558
|
-
window.ReturningAIWidget.isAuthenticated() // boolean
|
|
559
|
-
window.ReturningAIWidget.getTokenInfo() // token metadata (no token values exposed)
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
---
|
|
563
|
-
|
|
564
|
-
## Browser Support
|
|
565
|
-
|
|
566
|
-
Requires Custom Elements v1 + Shadow DOM v1.
|
|
567
|
-
|
|
568
|
-
| Browser | Minimum version |
|
|
569
|
-
|---------|----------------|
|
|
570
|
-
| Chrome | 67 |
|
|
571
|
-
| Firefox | 63 |
|
|
572
|
-
| Safari | 13 |
|
|
1
|
+
# @returningai/widget-sdk
|
|
2
|
+
|
|
3
|
+
Embed ReturningAI widgets on any website — React, Vue, Angular, or plain `<script>` tag. No external dependencies.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Get your credentials
|
|
10
|
+
|
|
11
|
+
Log in to your **ReturningAI dashboard** and go to **Community Settings > Integrations > SDK Access**. You will find:
|
|
12
|
+
|
|
13
|
+
- **Widget ID** — identifies your widget
|
|
14
|
+
- **API URL** — the base URL for widget authentication
|
|
15
|
+
- **Widget URL** — the URL that loads the widget content
|
|
16
|
+
|
|
17
|
+
### 2. Add the SDK to your page
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
21
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
22
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
23
|
+
data-widget-type="store"
|
|
24
|
+
data-theme="dark"
|
|
25
|
+
data-email="user@example.com"
|
|
26
|
+
api-url="YOUR_API_URL"
|
|
27
|
+
widget-url="YOUR_WIDGET_URL"
|
|
28
|
+
></script>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
That's it. The widget will authenticate and render automatically.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Authentication
|
|
36
|
+
|
|
37
|
+
### Public Embed (no backend needed)
|
|
38
|
+
|
|
39
|
+
The simplest way to embed a widget. The SDK handles everything — no server-side code required.
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
43
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
44
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
45
|
+
data-widget-type="store"
|
|
46
|
+
data-theme="dark"
|
|
47
|
+
data-email="user@example.com"
|
|
48
|
+
api-url="YOUR_API_URL"
|
|
49
|
+
widget-url="YOUR_WIDGET_URL"
|
|
50
|
+
></script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `data-email` attribute identifies the user. The SDK authenticates directly with the ReturningAI backend on the client side.
|
|
54
|
+
|
|
55
|
+
**When to use:** Demos, internal tools, or any scenario where you don't have a backend server.
|
|
56
|
+
|
|
57
|
+
### Access Key Embed (recommended for production)
|
|
58
|
+
|
|
59
|
+
Your access credentials stay on your server. Your server exchanges them for a **short-lived embed token (15 min)** and injects only that token into the page. No secret ever reaches the browser.
|
|
60
|
+
|
|
61
|
+
**Step 1 — Create an access key pair** (one-time, from your dashboard):
|
|
62
|
+
|
|
63
|
+
Go to **Community Settings > Integrations > SDK Access** and click **Create SDK Key**. Enter a name and optional allowed origins.
|
|
64
|
+
|
|
65
|
+
The dashboard will display your `accessId` and `accessKey`. The `accessKey` is shown **once only** — save it securely.
|
|
66
|
+
|
|
67
|
+
Store both values in your server environment variables.
|
|
68
|
+
|
|
69
|
+
**Step 2 — Exchange credentials for an embed token on every page load** (Node.js example):
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
// Runs on YOUR SERVER — never in the browser
|
|
73
|
+
const response = await fetch('https://YOUR_API_URL/v2/api/widget-access-keys/token', {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { 'Content-Type': 'application/json' },
|
|
76
|
+
body: JSON.stringify({
|
|
77
|
+
accessId: process.env.RAI_ACCESS_ID,
|
|
78
|
+
accessKey: process.env.RAI_ACCESS_KEY,
|
|
79
|
+
}),
|
|
80
|
+
})
|
|
81
|
+
const { data } = await response.json()
|
|
82
|
+
// data.embedToken expires in 15 minutes
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Step 3 — Embed** (only the short-lived token appears in HTML):
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
89
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
90
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
91
|
+
data-widget-type="store"
|
|
92
|
+
data-theme="dark"
|
|
93
|
+
data-email="user@example.com"
|
|
94
|
+
data-embed-token="eyJ..."
|
|
95
|
+
api-url="YOUR_API_URL"
|
|
96
|
+
widget-url="YOUR_WIDGET_URL"
|
|
97
|
+
></script>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The SDK validates the token on widget load. If the token is expired or invalid, the widget shows an error screen. Tokens expire after 15 minutes — regenerate on each page render.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Install
|
|
105
|
+
|
|
106
|
+
### CDN (no install needed)
|
|
107
|
+
|
|
108
|
+
```html
|
|
109
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"></script>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### npm / yarn / pnpm
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm install @returningai/widget-sdk
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Widget Types
|
|
121
|
+
|
|
122
|
+
Set the `data-widget-type` attribute to choose which widget to display. The Widget ID and Widget URL for each type are available in your dashboard.
|
|
123
|
+
|
|
124
|
+
| `data-widget-type` | Description |
|
|
125
|
+
|---------------------|-------------|
|
|
126
|
+
| `store` | Store / rewards widget |
|
|
127
|
+
| `channel` | Channel widget |
|
|
128
|
+
| `milestone` | Milestone widget |
|
|
129
|
+
| `social` | Social widget |
|
|
130
|
+
| `currency-view` | Currency widget |
|
|
131
|
+
| `referral-conditions` | Referral widget |
|
|
132
|
+
| `custom` | Custom widget |
|
|
133
|
+
|
|
134
|
+
### Store widget
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
138
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
139
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
140
|
+
data-widget-type="store"
|
|
141
|
+
data-theme="dark"
|
|
142
|
+
data-email="user@example.com"
|
|
143
|
+
api-url="YOUR_API_URL"
|
|
144
|
+
widget-url="YOUR_WIDGET_URL"
|
|
145
|
+
></script>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Channel widget
|
|
149
|
+
|
|
150
|
+
```html
|
|
151
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
152
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
153
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
154
|
+
data-widget-type="channel"
|
|
155
|
+
data-theme="dark"
|
|
156
|
+
data-email="user@example.com"
|
|
157
|
+
api-url="YOUR_API_URL"
|
|
158
|
+
widget-url="YOUR_WIDGET_URL"
|
|
159
|
+
></script>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
> **Note:** `YOUR_WIDGET_ID` for channel widgets is the base64-encoded channel ID — find it under **Community Settings > Channels** in your dashboard. Alternatively, use the [custom element approach](#framework-usage-custom-elements) with separate `community-id` and `channel-id` attributes.
|
|
163
|
+
|
|
164
|
+
### Social widget
|
|
165
|
+
|
|
166
|
+
```html
|
|
167
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
168
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
169
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
170
|
+
data-widget-type="social"
|
|
171
|
+
data-theme="dark"
|
|
172
|
+
data-email="user@example.com"
|
|
173
|
+
api-url="YOUR_API_URL"
|
|
174
|
+
widget-url="YOUR_WIDGET_URL"
|
|
175
|
+
></script>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Milestone widget
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
182
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
183
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
184
|
+
data-widget-type="milestone"
|
|
185
|
+
data-theme="dark"
|
|
186
|
+
data-email="user@example.com"
|
|
187
|
+
api-url="YOUR_API_URL"
|
|
188
|
+
widget-url="YOUR_WIDGET_URL"
|
|
189
|
+
></script>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Custom widget
|
|
193
|
+
|
|
194
|
+
```html
|
|
195
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
196
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
197
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
198
|
+
data-widget-type="custom"
|
|
199
|
+
data-theme="dark"
|
|
200
|
+
data-email="user@example.com"
|
|
201
|
+
api-url="YOUR_API_URL"
|
|
202
|
+
widget-url="YOUR_WIDGET_URL"
|
|
203
|
+
></script>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Attributes
|
|
209
|
+
|
|
210
|
+
There are two ways to identify your widget:
|
|
211
|
+
|
|
212
|
+
1. **Script-tag embed:** Use `data-widget-id` (a pre-encoded ID from your dashboard) on the `<script>` tag
|
|
213
|
+
2. **Custom element embed:** Use `community-id` (and `channel-id` for channel widgets) on the custom element tag
|
|
214
|
+
|
|
215
|
+
All attributes can be provided with or without the `data-` prefix — both work.
|
|
216
|
+
|
|
217
|
+
### Script-tag attributes
|
|
218
|
+
|
|
219
|
+
| Attribute | Required | Default | Description |
|
|
220
|
+
|-----------|----------|---------|-------------|
|
|
221
|
+
| `data-widget-id` | **Yes** | — | Your widget ID (from dashboard) |
|
|
222
|
+
| `data-widget-type` | **Yes** | `store` | Widget type (see table above) |
|
|
223
|
+
| `api-url` | **Yes**\* | — | Auth API base URL (from dashboard) |
|
|
224
|
+
| `widget-url` | **Yes**\* | — | Widget URL (from dashboard). \*Not required when using `data-bundle-url` |
|
|
225
|
+
| `data-bundle-url` | No | — | URL to the widget IIFE bundle — triggers [bundle mode](#bundle-mode) (non-iframe) |
|
|
226
|
+
| `data-domain-key` | Bundle mode | — | Environment key: `SGTR`, `STG`, or `PROD`. Required for bundle mode on external sites |
|
|
227
|
+
| `data-theme` | No | `light` | `light` or `dark` |
|
|
228
|
+
| `data-email` | Recommended | — | User's email for identification |
|
|
229
|
+
| `data-embed-token` | Access Key only | — | Short-lived token from your server |
|
|
230
|
+
| `data-locale` | No | — | BCP 47 locale tag (e.g. `fr-FR`) |
|
|
231
|
+
| `data-eager` | No | — | Load immediately instead of waiting until visible |
|
|
232
|
+
| `data-auto-refresh` | No | `true` | Auto-refresh access token before expiry |
|
|
233
|
+
| `data-debug` | No | `false` | Verbose console logging |
|
|
234
|
+
| `data-custom-data` | No | — | JSON object forwarded to the widget |
|
|
235
|
+
|
|
236
|
+
### Custom element attributes
|
|
237
|
+
|
|
238
|
+
| Attribute | Required | Default | Description |
|
|
239
|
+
|-----------|----------|---------|-------------|
|
|
240
|
+
| `community-id` | **Yes**\* | — | Your community ID (raw ObjectId from dashboard). \*Custom widgets use `widget-id` instead |
|
|
241
|
+
| `channel-id` | **Channel only** | — | Channel ID (raw ObjectId) — required for `<rai-channel-widget>` |
|
|
242
|
+
| `api-url` | **Yes** | — | Auth API base URL (from dashboard) |
|
|
243
|
+
| `widget-url` | **Yes**\* | — | Widget URL (from dashboard). \*Not required when using `bundle-url` |
|
|
244
|
+
| `bundle-url` | No | — | URL to the widget IIFE bundle — triggers [bundle mode](#bundle-mode) (non-iframe) |
|
|
245
|
+
| `domain-key` | Bundle mode | — | Environment key: `SGTR`, `STG`, or `PROD`. Required for bundle mode on external sites |
|
|
246
|
+
| `theme` | No | `light` | `light` or `dark` |
|
|
247
|
+
| `data-email` | Recommended | — | User's email for identification |
|
|
248
|
+
| `embed-token` | Access Key only | — | Short-lived token from your server |
|
|
249
|
+
| `width` | No | `100%` | CSS width |
|
|
250
|
+
| `height` | No | `600px` | CSS height |
|
|
251
|
+
| `locale` | No | — | BCP 47 locale tag (e.g. `fr-FR`) |
|
|
252
|
+
| `eager` | No | — | Load immediately instead of waiting until visible |
|
|
253
|
+
| `auto-refresh` | No | `true` | Auto-refresh access token before expiry |
|
|
254
|
+
| `debug` | No | `false` | Verbose console logging |
|
|
255
|
+
| `custom-data` | No | — | JSON object forwarded to the widget |
|
|
256
|
+
|
|
257
|
+
> **`widget-id` vs `community-id`:** The script-tag method uses `data-widget-id` which is a pre-encoded identifier (base64). The custom element method uses raw ObjectIds — `community-id` for most widget types, plus `channel-id` for channel widgets. The SDK handles the encoding internally.
|
|
258
|
+
|
|
259
|
+
### Container `<div>` (script-tag method only)
|
|
260
|
+
|
|
261
|
+
The SDK looks for a `<div>` with `id="returning-ai-widget-{YOUR_WIDGET_ID}"`. Size the div to control the widget dimensions:
|
|
262
|
+
|
|
263
|
+
```html
|
|
264
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Custom elements don't need a container div — they size themselves using `width` and `height` attributes (defaults: `100%` and `600px`).
|
|
268
|
+
|
|
269
|
+
### User Identifier Attributes
|
|
270
|
+
|
|
271
|
+
Pass any `data-*` attribute to identify the current user. Which identifiers are available is configured per community in your dashboard.
|
|
272
|
+
|
|
273
|
+
```html
|
|
274
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
275
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
276
|
+
data-widget-type="store"
|
|
277
|
+
data-email="user@example.com"
|
|
278
|
+
data-user-id="12345"
|
|
279
|
+
data-account-id="abc"
|
|
280
|
+
api-url="YOUR_API_URL"
|
|
281
|
+
widget-url="YOUR_WIDGET_URL"
|
|
282
|
+
></script>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Any `data-*` attribute not reserved by the SDK is forwarded to the auth API as a user identifier.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Bundle Mode
|
|
290
|
+
|
|
291
|
+
When you set the `bundle-url` attribute, the widget renders directly in the page DOM instead of inside an iframe. This gives full CSS cascade — `html[data-theme]` and Tailwind classes apply to the widget content naturally.
|
|
292
|
+
|
|
293
|
+
`widget-url` is not needed in bundle mode. `domain-key` is required so the widget resolves the correct environment URLs.
|
|
294
|
+
|
|
295
|
+
```html
|
|
296
|
+
<!-- Script-tag approach -->
|
|
297
|
+
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:100vh"></div>
|
|
298
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
299
|
+
data-widget-id="YOUR_WIDGET_ID"
|
|
300
|
+
data-widget-type="store"
|
|
301
|
+
data-theme="dark"
|
|
302
|
+
data-email="user@example.com"
|
|
303
|
+
data-bundle-url="YOUR_BUNDLE_URL"
|
|
304
|
+
data-domain-key="YOUR_DOMAIN_KEY"
|
|
305
|
+
api-url="YOUR_API_URL"
|
|
306
|
+
data-eager
|
|
307
|
+
></script>
|
|
308
|
+
|
|
309
|
+
<!-- Custom element approach -->
|
|
310
|
+
<rai-store-widget
|
|
311
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
312
|
+
api-url="YOUR_API_URL"
|
|
313
|
+
bundle-url="YOUR_BUNDLE_URL"
|
|
314
|
+
domain-key="YOUR_DOMAIN_KEY"
|
|
315
|
+
data-email="user@example.com"
|
|
316
|
+
theme="dark"
|
|
317
|
+
width="100%"
|
|
318
|
+
height="100vh"
|
|
319
|
+
eager
|
|
320
|
+
></rai-store-widget>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Each widget type has its own IIFE bundle and global name:
|
|
324
|
+
|
|
325
|
+
| Widget type | Bundle global | Custom element tag |
|
|
326
|
+
|-------------|--------------|-------------------|
|
|
327
|
+
| `store` | `RaiStoreWidget` | `<rai-store-widget>` |
|
|
328
|
+
| `channel` | `RaiChannelWidget` | `<rai-channel-widget>` |
|
|
329
|
+
| `social` | `RaiSocialWidget` | `<rai-social-widget>` |
|
|
330
|
+
| `milestone` | `RaiMilestoneWidget` | `<rai-milestone-widget>` |
|
|
331
|
+
| `currency-view` | `RaiCurrencyWidget` | `<rai-currency-widget>` |
|
|
332
|
+
| `referral-conditions` | `RaiReferralWidget` | `<rai-referral-widget>` |
|
|
333
|
+
| `custom` | `RaiCustomWidget` | `<rai-custom-widget>` |
|
|
334
|
+
|
|
335
|
+
The bundle must export a `mount(container, config)` function on its global (e.g. `window.RaiStoreWidget.mount`).
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Framework Usage (Custom Elements)
|
|
340
|
+
|
|
341
|
+
When using a frontend framework (React, Vue, Angular), you can use custom HTML element tags instead of the script-tag method. Custom elements use raw IDs (`community-id`, `channel-id`) instead of the pre-encoded `data-widget-id`.
|
|
342
|
+
|
|
343
|
+
### Plain HTML
|
|
344
|
+
|
|
345
|
+
```html
|
|
346
|
+
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"></script>
|
|
347
|
+
|
|
348
|
+
<!-- Store widget -->
|
|
349
|
+
<rai-store-widget
|
|
350
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
351
|
+
theme="dark"
|
|
352
|
+
data-email="user@example.com"
|
|
353
|
+
api-url="YOUR_API_URL"
|
|
354
|
+
widget-url="YOUR_WIDGET_URL"
|
|
355
|
+
></rai-store-widget>
|
|
356
|
+
|
|
357
|
+
<!-- Channel widget — requires both community-id AND channel-id -->
|
|
358
|
+
<rai-channel-widget
|
|
359
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
360
|
+
channel-id="YOUR_CHANNEL_ID"
|
|
361
|
+
theme="dark"
|
|
362
|
+
data-email="user@example.com"
|
|
363
|
+
api-url="YOUR_API_URL"
|
|
364
|
+
widget-url="YOUR_WIDGET_URL"
|
|
365
|
+
></rai-channel-widget>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### React (TypeScript)
|
|
369
|
+
|
|
370
|
+
Types are included — no manual JSX declarations needed.
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
import '@returningai/widget-sdk'
|
|
374
|
+
|
|
375
|
+
export function StoreEmbed({ email }: { email: string }) {
|
|
376
|
+
return (
|
|
377
|
+
<rai-store-widget
|
|
378
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
379
|
+
theme="dark"
|
|
380
|
+
data-email={email}
|
|
381
|
+
api-url="YOUR_API_URL"
|
|
382
|
+
widget-url="YOUR_WIDGET_URL"
|
|
383
|
+
/>
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export function ChannelEmbed({ email }: { email: string }) {
|
|
388
|
+
return (
|
|
389
|
+
<rai-channel-widget
|
|
390
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
391
|
+
channel-id="YOUR_CHANNEL_ID"
|
|
392
|
+
theme="dark"
|
|
393
|
+
data-email={email}
|
|
394
|
+
api-url="YOUR_API_URL"
|
|
395
|
+
widget-url="YOUR_WIDGET_URL"
|
|
396
|
+
/>
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Vue 3
|
|
402
|
+
|
|
403
|
+
```vue
|
|
404
|
+
<script setup>
|
|
405
|
+
import '@returningai/widget-sdk'
|
|
406
|
+
</script>
|
|
407
|
+
|
|
408
|
+
<template>
|
|
409
|
+
<!-- Store widget -->
|
|
410
|
+
<rai-store-widget
|
|
411
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
412
|
+
theme="dark"
|
|
413
|
+
:data-email="user.email"
|
|
414
|
+
api-url="YOUR_API_URL"
|
|
415
|
+
widget-url="YOUR_WIDGET_URL"
|
|
416
|
+
/>
|
|
417
|
+
|
|
418
|
+
<!-- Channel widget -->
|
|
419
|
+
<rai-channel-widget
|
|
420
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
421
|
+
channel-id="YOUR_CHANNEL_ID"
|
|
422
|
+
theme="dark"
|
|
423
|
+
:data-email="user.email"
|
|
424
|
+
api-url="YOUR_API_URL"
|
|
425
|
+
widget-url="YOUR_WIDGET_URL"
|
|
426
|
+
/>
|
|
427
|
+
</template>
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Angular
|
|
431
|
+
|
|
432
|
+
```ts
|
|
433
|
+
// app.module.ts
|
|
434
|
+
import '@returningai/widget-sdk'
|
|
435
|
+
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
|
|
436
|
+
|
|
437
|
+
@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
```html
|
|
441
|
+
<!-- Store widget -->
|
|
442
|
+
<rai-store-widget
|
|
443
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
444
|
+
theme="dark"
|
|
445
|
+
[attr.data-email]="user.email"
|
|
446
|
+
api-url="YOUR_API_URL"
|
|
447
|
+
widget-url="YOUR_WIDGET_URL"
|
|
448
|
+
></rai-store-widget>
|
|
449
|
+
|
|
450
|
+
<!-- Channel widget -->
|
|
451
|
+
<rai-channel-widget
|
|
452
|
+
community-id="YOUR_COMMUNITY_ID"
|
|
453
|
+
channel-id="YOUR_CHANNEL_ID"
|
|
454
|
+
theme="dark"
|
|
455
|
+
[attr.data-email]="user.email"
|
|
456
|
+
api-url="YOUR_API_URL"
|
|
457
|
+
widget-url="YOUR_WIDGET_URL"
|
|
458
|
+
></rai-channel-widget>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Available custom element tags
|
|
462
|
+
|
|
463
|
+
| Tag | Required attributes | Widget type |
|
|
464
|
+
|-----|-------------------|-------------|
|
|
465
|
+
| `<rai-store-widget>` | `community-id` | Store |
|
|
466
|
+
| `<rai-channel-widget>` | `community-id` + `channel-id` | Channel |
|
|
467
|
+
| `<rai-milestone-widget>` | `community-id` | Milestone |
|
|
468
|
+
| `<rai-social-widget>` | `community-id` | Social |
|
|
469
|
+
| `<rai-currency-widget>` | `community-id` | Currency |
|
|
470
|
+
| `<rai-referral-widget>` | `community-id` | Referral |
|
|
471
|
+
| `<rai-custom-widget>` | `widget-id` (not `community-id`) | Custom |
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## DOM Events
|
|
476
|
+
|
|
477
|
+
Listen for widget lifecycle events:
|
|
478
|
+
|
|
479
|
+
| Event | `detail` | Fired when |
|
|
480
|
+
|-------|----------|-----------|
|
|
481
|
+
| `rai-authenticated` | `{}` | Auth succeeded, before widget mounts |
|
|
482
|
+
| `rai-ready` | `{}` | `WIDGET_READY` received, loader hidden (iframe mode) |
|
|
483
|
+
| `rai-mounted` | `{}` | Widget bundle mounted successfully (bundle mode) |
|
|
484
|
+
| `rai-error` | `{ message }` | Auth failed after all retries |
|
|
485
|
+
| `rai-logout` | `{}` | Widget logged out |
|
|
486
|
+
| `rai-height-change` | `{ height }` | iframe resized (after debounce) |
|
|
487
|
+
|
|
488
|
+
```js
|
|
489
|
+
// Script-tag embed
|
|
490
|
+
const widget = document.querySelector('[data-widget-id]')
|
|
491
|
+
|
|
492
|
+
// Custom element embed
|
|
493
|
+
const widget = document.querySelector('rai-store-widget')
|
|
494
|
+
|
|
495
|
+
widget.addEventListener('rai-authenticated', () => { /* auth succeeded */ })
|
|
496
|
+
widget.addEventListener('rai-ready', () => { /* widget loaded and visible (iframe mode) */ })
|
|
497
|
+
widget.addEventListener('rai-mounted', () => { /* widget mounted (bundle mode) */ })
|
|
498
|
+
widget.addEventListener('rai-error', (e) => console.error(e.detail.message))
|
|
499
|
+
widget.addEventListener('rai-logout', () => { /* user logged out */ })
|
|
500
|
+
widget.addEventListener('rai-height-change', (e) => console.log(e.detail.height))
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## Public API
|
|
506
|
+
|
|
507
|
+
After the SDK loads, `window.ReturningAIWidget` is available:
|
|
508
|
+
|
|
509
|
+
```js
|
|
510
|
+
window.ReturningAIWidget.version // current SDK version
|
|
511
|
+
await window.ReturningAIWidget.reload() // re-runs auth flow and reloads widget
|
|
512
|
+
await window.ReturningAIWidget.logout() // clears tokens and removes widget
|
|
513
|
+
window.ReturningAIWidget.isAuthenticated() // boolean
|
|
514
|
+
window.ReturningAIWidget.getTokenInfo() // token metadata (no token values exposed)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Browser Support
|
|
520
|
+
|
|
521
|
+
Requires Custom Elements v1 + Shadow DOM v1.
|
|
522
|
+
|
|
523
|
+
| Browser | Minimum version |
|
|
524
|
+
|---------|----------------|
|
|
525
|
+
| Chrome | 67 |
|
|
526
|
+
| Firefox | 63 |
|
|
527
|
+
| Safari | 13 |
|