@encorekit/web-sdk 1.1.20 → 2.0.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 +135 -0
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/umd/encore.min.js +1 -1
- package/dist/umd/encore.min.js.map +1 -1
- package/package.json +4 -3
- package/types/analytics/AnalyticsClient.d.ts +11 -1
- package/types/analytics/AnalyticsClient.d.ts.map +1 -1
- package/types/analytics/events.d.ts +215 -3
- package/types/analytics/events.d.ts.map +1 -1
- package/types/analytics/transport.d.ts.map +1 -1
- package/types/api/APIClient.d.ts +32 -7
- package/types/api/APIClient.d.ts.map +1 -1
- package/types/api/generated/types.d.ts +568 -11
- package/types/api/generated/types.d.ts.map +1 -1
- package/types/core/DisplayResolver.d.ts +121 -0
- package/types/core/DisplayResolver.d.ts.map +1 -0
- package/types/core/Encore.d.ts.map +1 -1
- package/types/core/OfferManager.d.ts +50 -9
- package/types/core/OfferManager.d.ts.map +1 -1
- package/types/core/PlacementBuilder.d.ts +24 -1
- package/types/core/PlacementBuilder.d.ts.map +1 -1
- package/types/core/useCase.d.ts +21 -0
- package/types/core/useCase.d.ts.map +1 -0
- package/types/core/version.d.ts +1 -1
- package/types/core/version.d.ts.map +1 -1
- package/types/types.d.ts +118 -8
- package/types/types.d.ts.map +1 -1
- package/types/ui/OfferCard.d.ts.map +1 -1
- package/types/ui/OfferCarousel.d.ts +23 -0
- package/types/ui/OfferCarousel.d.ts.map +1 -1
- package/types/ui/PrimerScreen.d.ts +34 -0
- package/types/ui/PrimerScreen.d.ts.map +1 -0
- package/types/ui/RedemptionScreen.d.ts +31 -7
- package/types/ui/RedemptionScreen.d.ts.map +1 -1
- package/types/ui/ThankYouLayout.d.ts +11 -0
- package/types/ui/ThankYouLayout.d.ts.map +1 -1
- package/types/ui/brandComponents.d.ts +45 -0
- package/types/ui/brandComponents.d.ts.map +1 -0
- package/types/ui/safeImageSrc.d.ts +15 -0
- package/types/ui/safeImageSrc.d.ts.map +1 -0
- package/types/ui/styles.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@ A JavaScript/TypeScript SDK that enables web applications to display targeted of
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- 🎯 **Targeted Offer Presentation** - Display offers at critical moments (cancellation flows, paywalls, onboarding)
|
|
8
|
+
- 🎁 **Use Cases** - Churn intervention (the default) or post-action rewards — see [Use Cases](#use-cases)
|
|
8
9
|
- 🔐 **Entitlement Management** - Two-tier system (provisional + verified) for instant UX and reliable billing
|
|
9
10
|
- 📱 **Framework Agnostic** - Works with React, Vue, Angular, Svelte, vanilla JavaScript, or any web framework
|
|
10
11
|
- 🎨 **Responsive UI** - Beautiful, accessible modal interface that works on desktop and mobile
|
|
@@ -102,6 +103,140 @@ Notes:
|
|
|
102
103
|
verify entitlements/conversions server-side by user, never from the client).
|
|
103
104
|
`show()` never rejects: failures resolve as `{ status: 'dismissed', reason }`.
|
|
104
105
|
|
|
106
|
+
## Use Cases
|
|
107
|
+
|
|
108
|
+
A placement's **use case** says *why* it presents. It defaults to
|
|
109
|
+
`'churn-intervention'` — the behaviour every caller already had before this
|
|
110
|
+
dimension existed — so existing integrations need no change.
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Reward a user for something they just did. No entitlement is granted.
|
|
114
|
+
const result = await Encore.placement('milestone_reached')
|
|
115
|
+
.useCase('post-action-reward')
|
|
116
|
+
.show();
|
|
117
|
+
|
|
118
|
+
if (result.status === 'claimed') {
|
|
119
|
+
// The user claimed an offer. Render your own confirmation.
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
It is also a plain placement option, if you prefer that form:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
Encore.placement('milestone_reached', { useCase: 'post-action-reward' });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Value | Meaning |
|
|
130
|
+
|:------|:--------|
|
|
131
|
+
| `'churn-intervention'` | The default. A user is cancelling or downgrading; the offer is an alternative to leaving. |
|
|
132
|
+
| `'post-action-reward'` | The user completed something worth celebrating — a purchase, a milestone, a streak, a level. The offer is a gift. |
|
|
133
|
+
|
|
134
|
+
### Supplying your own headline and subheadline
|
|
135
|
+
|
|
136
|
+
Pass your copy at presentation time. This is the intended way to set it — you
|
|
137
|
+
know what the user just did, so you can name it:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
await Encore.placement('milestone_reached')
|
|
141
|
+
.useCase('post-action-reward')
|
|
142
|
+
.headline('Nice work, Sam!')
|
|
143
|
+
.subheadline('That is your fifth week running')
|
|
144
|
+
.show();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Both are **per-call overrides**: they beat whatever copy Encore resolved for the
|
|
148
|
+
surface, and they work on either use case. `.headline()` fills the sheet's
|
|
149
|
+
primary heading and `.subheadline()` the line under it.
|
|
150
|
+
|
|
151
|
+
They are also available as a plain option, if you are already passing others:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
await Encore.show(undefined, {
|
|
155
|
+
useCase: 'post-action-reward',
|
|
156
|
+
header: { title: 'Nice work, Sam!', subtitle: 'That is your fifth week running' },
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
> **Blank falls through — it does not clear the copy.** A blank or
|
|
161
|
+
> whitespace-only value is treated as "not supplied" and falls through to the
|
|
162
|
+
> copy Encore resolved, so passing `''` is never a way to blank the sheet. Omit
|
|
163
|
+
> the call instead. This keeps a value that is empty because an interpolation
|
|
164
|
+
> came back empty (`.headline(\`Nice work, ${name}!\`)` with no `name`) from
|
|
165
|
+
> rendering a headless sheet.
|
|
166
|
+
|
|
167
|
+
If you supply neither, the sheet falls back to Encore's resolved copy for the
|
|
168
|
+
surface, and finally to a built-in string, so the heading is never empty.
|
|
169
|
+
|
|
170
|
+
### `post-action-reward` grants no entitlement
|
|
171
|
+
|
|
172
|
+
A reward claim is a gift the brand funds directly, not a subscription unlock. So
|
|
173
|
+
`show()` resolves `{ status: 'claimed' }` and **no entitlement is granted** — on
|
|
174
|
+
this path the SDK skips the automatic provisional grant it performs for
|
|
175
|
+
`'churn-intervention'`, so no grant signal reaches Encore. Nothing was promised,
|
|
176
|
+
so nothing is unlocked. (Reward activation is confirmed server-side via the
|
|
177
|
+
offer-completed webhook, an entirely separate mechanism.)
|
|
178
|
+
|
|
179
|
+
This is why `claimed` is its own result and not folded into `dismissed`: a user
|
|
180
|
+
who successfully claimed a reward must never run your "user declined" branch.
|
|
181
|
+
|
|
182
|
+
> That guarantee is on `show()`'s `ShowResult`. The deprecated `presentOffer()`
|
|
183
|
+
> predates it and still reports a **deferred** claim as `granted: false`, so use
|
|
184
|
+
> `show()` for any reward placement.
|
|
185
|
+
|
|
186
|
+
### Unrecognised values fail closed
|
|
187
|
+
|
|
188
|
+
Anything that is not one of the two values above is rejected before anything is
|
|
189
|
+
presented, rather than quietly falling back to the churn-intervention surface.
|
|
190
|
+
`show()` still never rejects — it resolves:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
{ status: 'dismissed', reason: { type: 'error', error: { code: 'INVALID_REQUEST', … } } }
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If you call `Encore.show({ onError, onNotGranted }, { useCase })`, both callbacks
|
|
197
|
+
fire. Via `Encore.placement(...)` only the builder's `.onNotGranted()` exists —
|
|
198
|
+
there is no `.onError()` on the builder — so read the returned `reason.error`.
|
|
199
|
+
|
|
200
|
+
### Enablement affects SPEED, not availability
|
|
201
|
+
|
|
202
|
+
Requesting a use case is all it takes to be served it. There is no setup call,
|
|
203
|
+
and you do not need Encore to switch anything on first:
|
|
204
|
+
|
|
205
|
+
| Your app | What happens |
|
|
206
|
+
|:---------|:-------------|
|
|
207
|
+
| Enabled for the use case | Its config arrives with the one `/config` fetch at `configure()` — the first presentation is **instant** |
|
|
208
|
+
| Not enabled | The SDK fetches that one surface on the **first** present, then caches it — **slower once**, instant thereafter |
|
|
209
|
+
|
|
210
|
+
When the second row applies the SDK logs a one-off `[INTEGRATION]` notice saying
|
|
211
|
+
the surface was not prefetched. It is a **speed hint, not an error** — nothing has
|
|
212
|
+
failed. Ask Encore to enable the use case for your app to remove the first-present
|
|
213
|
+
round trip.
|
|
214
|
+
|
|
215
|
+
> **Encore can still switch a surface off.** An explicit kill switch is the one
|
|
216
|
+
> thing that blocks serving, and it is deliberate — it is how a live surface is
|
|
217
|
+
> stopped without a deploy. A switched-off surface no-ops exactly as below.
|
|
218
|
+
|
|
219
|
+
### When nothing presents
|
|
220
|
+
|
|
221
|
+
A use case that cannot be served resolves `{ status: 'unavailable' }`, reports
|
|
222
|
+
`sdk_offer_presentation_failed` with reason `no_template`, and **never** falls back
|
|
223
|
+
to another use case's offers or copy. It does not throw.
|
|
224
|
+
|
|
225
|
+
`unavailable` is the same result you get when there are simply no eligible offers,
|
|
226
|
+
and it has several causes — so do not read it as "not enabled":
|
|
227
|
+
|
|
228
|
+
- Encore has switched the surface off, or no variant was eligible for it;
|
|
229
|
+
- the `/config` response had not arrived within ~2.5s of the call, or failed;
|
|
230
|
+
- the on-demand fetch for the surface failed.
|
|
231
|
+
|
|
232
|
+
> ⚠️ **This is silent by default.** The explanatory log is emitted at `info`, and
|
|
233
|
+
> every log level is gated behind `logLevel: 'debug'` — which is not the default.
|
|
234
|
+
> When integrating a reward placement, configure `logLevel: 'debug'` and confirm
|
|
235
|
+
> you see an actual presentation. A clean console is not evidence that it worked.
|
|
236
|
+
|
|
237
|
+
See [the use-case serving model](https://github.com/EncoreKit/web-sdk/blob/main/docs/architecture/use-case-serving.md)
|
|
238
|
+
for the full design note.
|
|
239
|
+
|
|
105
240
|
## Browser Support
|
|
106
241
|
|
|
107
242
|
- Chrome/Edge (last 2 versions)
|