@proveanything/smartlinks 1.13.6 → 1.13.9
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 +37 -14
- package/dist/README.md +15 -10
- package/dist/api/analytics.js +6 -3
- package/dist/api/appObjects.d.ts +5 -2
- package/dist/api/appObjects.js +5 -2
- package/dist/api/authKit.d.ts +13 -1
- package/dist/api/authKit.js +34 -0
- package/dist/api/comms.d.ts +1 -1
- package/dist/api/comms.js +14 -3
- package/dist/docs/API_SUMMARY.md +254 -32
- package/dist/docs/auth-kit.md +55 -0
- package/dist/docs/comms.md +4 -4
- package/dist/docs/interactions.md +200 -0
- package/dist/docs/overview.md +2 -0
- package/dist/openapi.yaml +532 -35
- package/dist/types/appObjects.d.ts +5 -0
- package/dist/types/authKit.d.ts +57 -0
- package/dist/types/comms.d.ts +6 -5
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/interaction.d.ts +97 -0
- package/docs/API_SUMMARY.md +254 -32
- package/docs/auth-kit.md +55 -0
- package/docs/comms.md +4 -4
- package/docs/interactions.md +200 -0
- package/docs/overview.md +2 -0
- package/openapi.yaml +532 -35
- package/package.json +1 -1
|
@@ -280,6 +280,195 @@ When defining a journey trigger, reference the `interactionId` that should fire
|
|
|
280
280
|
|
|
281
281
|
---
|
|
282
282
|
|
|
283
|
+
## Interaction Effects
|
|
284
|
+
|
|
285
|
+
**Interaction effects** are automatic side-effects that fire immediately after an interaction event is recorded. They are defined directly on the interaction definition (`data.effects`) and run inline, fire-and-forget — they never block or fail the interaction response.
|
|
286
|
+
|
|
287
|
+
Common use cases: send a confirmation email, post a webhook to a CRM, tag the contact, award loyalty points, create an app record, or add the contact to a segment.
|
|
288
|
+
|
|
289
|
+
### How It Works
|
|
290
|
+
|
|
291
|
+
1. Event is logged to BigQuery
|
|
292
|
+
2. Interaction definition is loaded
|
|
293
|
+
3. Each configured effect runs **in order**, fire-and-forget
|
|
294
|
+
4. Response is returned to the caller immediately
|
|
295
|
+
|
|
296
|
+
A failure in one effect is logged and swallowed; subsequent effects still run.
|
|
297
|
+
|
|
298
|
+
> **Note:** `transactional` and `webhook` effects currently run inline. They are planned to move to background jobs for retry-on-failure support once the jobs infrastructure is fully operational.
|
|
299
|
+
|
|
300
|
+
### Configuring Effects
|
|
301
|
+
|
|
302
|
+
Pass `data.effects` when creating or updating an interaction type:
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
await SL.interactions.create(collectionId, {
|
|
306
|
+
id: 'donation',
|
|
307
|
+
appId: 'my-app',
|
|
308
|
+
permissions: { allowPublicSubmit: true },
|
|
309
|
+
data: {
|
|
310
|
+
effects: [
|
|
311
|
+
{
|
|
312
|
+
type: 'transactional',
|
|
313
|
+
config: {
|
|
314
|
+
templateId: 'tmpl_donation_receipt',
|
|
315
|
+
channel: 'email',
|
|
316
|
+
props: {
|
|
317
|
+
donationAmount: '{{metadata.amount}}',
|
|
318
|
+
campaignName: '{{metadata.campaign}}',
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
type: 'tag',
|
|
324
|
+
config: { tags: ['donor'] },
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Token Interpolation
|
|
332
|
+
|
|
333
|
+
All effect `config` values support `{{token}}` interpolation resolved from the event context at runtime. Nested paths using dot notation are supported (e.g. `{{metadata.amount}}`).
|
|
334
|
+
|
|
335
|
+
| Token | Description |
|
|
336
|
+
|---|---|
|
|
337
|
+
| `{{eventId}}` | BigQuery event UUID |
|
|
338
|
+
| `{{collectionId}}` | Collection / brand ID |
|
|
339
|
+
| `{{appId}}` | App ID that submitted the event |
|
|
340
|
+
| `{{interactionId}}` | Interaction definition ID |
|
|
341
|
+
| `{{contactId}}` | Contact UUID (if resolved) |
|
|
342
|
+
| `{{userId}}` | Firebase UID (if authenticated) |
|
|
343
|
+
| `{{productId}}` | Product ID (if provided with event) |
|
|
344
|
+
| `{{proofId}}` | Proof ID (if provided with event) |
|
|
345
|
+
| `{{variantId}}` | Variant ID (if provided with event) |
|
|
346
|
+
| `{{batchId}}` | Batch ID (if provided with event) |
|
|
347
|
+
| `{{outcome}}` | Event outcome (e.g. `"submitted"`) |
|
|
348
|
+
| `{{eventType}}` | Event type string |
|
|
349
|
+
| `{{source}}` | Event source string |
|
|
350
|
+
| `{{timestamp}}` | ISO 8601 event timestamp |
|
|
351
|
+
| `{{metadata.*}}` | Any key from the event `metadata` object |
|
|
352
|
+
|
|
353
|
+
Tokens that resolve to `null` or `undefined` become an empty string.
|
|
354
|
+
|
|
355
|
+
### Effect Types
|
|
356
|
+
|
|
357
|
+
#### `loyalty`
|
|
358
|
+
|
|
359
|
+
Awards loyalty points by evaluating `LoyaltyEarningRule` records configured against this interaction. Earning rules are managed separately via the Loyalty API. If no rules are configured, this effect is a no-op.
|
|
360
|
+
|
|
361
|
+
```json
|
|
362
|
+
{ "type": "loyalty", "config": {} }
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### `transactional`
|
|
366
|
+
|
|
367
|
+
Sends a message to the contact using a comms template. Supports all channels with full Liquid template hydration.
|
|
368
|
+
|
|
369
|
+
```json
|
|
370
|
+
{
|
|
371
|
+
"type": "transactional",
|
|
372
|
+
"config": {
|
|
373
|
+
"templateId": "tmpl_donation_receipt",
|
|
374
|
+
"channel": "email",
|
|
375
|
+
"props": {
|
|
376
|
+
"donationAmount": "{{metadata.amount}}"
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
`channel` defaults to `"preferred"` — auto-selects the contact's best available channel respecting consent, suppression, and template availability. Optionally pass `include` to hydrate product/proof/user context, and `props` for additional Liquid variables.
|
|
383
|
+
|
|
384
|
+
#### `webhook`
|
|
385
|
+
|
|
386
|
+
Posts a JSON payload to an HTTP endpoint. All config values support `{{token}}` interpolation.
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"type": "webhook",
|
|
391
|
+
"config": {
|
|
392
|
+
"url": "https://crm.example.com/api/events",
|
|
393
|
+
"headers": { "Authorization": "Bearer sk_live_abc123" },
|
|
394
|
+
"body": {
|
|
395
|
+
"contactId": "{{contactId}}",
|
|
396
|
+
"amount": "{{metadata.amount}}"
|
|
397
|
+
},
|
|
398
|
+
"timeout": 8000
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
When `body` is omitted, a standard payload is sent containing `eventId`, `collectionId`, `appId`, `interactionId`, `contactId`, `userId`, `productId`, `proofId`, `outcome`, `eventType`, `metadata`, and `timestamp`.
|
|
404
|
+
|
|
405
|
+
#### `tag`
|
|
406
|
+
|
|
407
|
+
Adds or removes string tags on the contact record. Skipped if there is no `contactId` on the event.
|
|
408
|
+
|
|
409
|
+
```json
|
|
410
|
+
{
|
|
411
|
+
"type": "tag",
|
|
412
|
+
"config": {
|
|
413
|
+
"tags": ["donor", "tier-{{metadata.tier}}"],
|
|
414
|
+
"action": "add"
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
`action` defaults to `"add"`. Duplicate adds are no-ops; removing a tag not present is a no-op.
|
|
420
|
+
|
|
421
|
+
#### `appRecord`
|
|
422
|
+
|
|
423
|
+
Creates or upserts an app record scoped to the event context. Use `singletonPer` for cardinality control — if a matching singleton already exists it is updated rather than duplicated.
|
|
424
|
+
|
|
425
|
+
```json
|
|
426
|
+
{
|
|
427
|
+
"type": "appRecord",
|
|
428
|
+
"config": {
|
|
429
|
+
"recordType": "participation",
|
|
430
|
+
"singletonPer": "contact",
|
|
431
|
+
"data": {
|
|
432
|
+
"participatedAt": "{{timestamp}}",
|
|
433
|
+
"outcome": "{{outcome}}"
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Common `singletonPer` values: `"contact"`, `"product"`, `"proof"`, `"global"`.
|
|
440
|
+
|
|
441
|
+
#### `segment`
|
|
442
|
+
|
|
443
|
+
Adds or removes the contact from a **static** segment. Skipped if there is no `contactId` on the event.
|
|
444
|
+
|
|
445
|
+
```json
|
|
446
|
+
{
|
|
447
|
+
"type": "segment",
|
|
448
|
+
"config": {
|
|
449
|
+
"segmentId": "seg_donors_2026",
|
|
450
|
+
"action": "add"
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The segment must already exist and be of `filterType: 'static'`.
|
|
456
|
+
|
|
457
|
+
### Effects Error Handling
|
|
458
|
+
|
|
459
|
+
| Scenario | Behaviour |
|
|
460
|
+
|---|---|
|
|
461
|
+
| Effect throws (e.g. template not found, webhook 500) | Error logged server-side; next effect continues |
|
|
462
|
+
| Contact has no email, `transactional` channel = `email` | Effect throws, logged, skipped |
|
|
463
|
+
| `contactId` absent on anonymous event | `tag`, `appRecord`, `segment` log a warning and skip |
|
|
464
|
+
| Unknown `type` value | Warning logged, effect skipped |
|
|
465
|
+
| `loyalty` — no earning rules configured | Silent no-op |
|
|
466
|
+
| Interaction has no `data.effects` | No effects run, no overhead |
|
|
467
|
+
|
|
468
|
+
Effects do **not** propagate errors back to the API caller.
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
283
472
|
## TypeScript Types
|
|
284
473
|
|
|
285
474
|
```typescript
|
|
@@ -299,6 +488,17 @@ import type {
|
|
|
299
488
|
AdminInteractionsCountsByOutcomeRequest,
|
|
300
489
|
PublicInteractionsCountsByOutcomeRequest,
|
|
301
490
|
PublicInteractionsByUserRequest,
|
|
491
|
+
// Effects
|
|
492
|
+
InteractionEffect, // Single effect entry { type, config? }
|
|
493
|
+
EffectType, // 'loyalty' | 'transactional' | 'webhook' | 'tag' | 'appRecord' | 'segment'
|
|
494
|
+
EffectConfig, // Union of all effect config shapes
|
|
495
|
+
LoyaltyEffectConfig,
|
|
496
|
+
TransactionalEffectConfig,
|
|
497
|
+
WebhookEffectConfig,
|
|
498
|
+
TagEffectConfig,
|
|
499
|
+
AppRecordEffectConfig,
|
|
500
|
+
SegmentEffectConfig,
|
|
501
|
+
InteractionEventContext, // Token interpolation context shape
|
|
302
502
|
} from '@proveanything/smartlinks';
|
|
303
503
|
```
|
|
304
504
|
|
package/dist/docs/overview.md
CHANGED
|
@@ -43,6 +43,8 @@ Widgets and containers run in the parent's React tree (not iframes). Mobile Admi
|
|
|
43
43
|
|
|
44
44
|
The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive documentation in `node_modules/@proveanything/smartlinks/docs/`. **Always read these files for detailed implementation guidance.**
|
|
45
45
|
|
|
46
|
+
> Product endpoints: use `products` (plural) for new integrations. The older `product` (singular) namespace remains for backward compatibility and is deprecated.
|
|
47
|
+
|
|
46
48
|
> **Minimum SDK version: `1.4.1`** — Ensure `@proveanything/smartlinks` is at least this version. If not, update with `npm install @proveanything/smartlinks@latest`.
|
|
47
49
|
|
|
48
50
|
| Topic | File | When to Use |
|