@encorekit/web-sdk 2.0.3 → 2.0.6
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 +112 -40
- 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/embed/README.md +82 -367
- package/examples/ios-webview/EncoreURLBuilder.swift +179 -61
- package/examples/ios-webview/README.md +75 -354
- package/examples/ios-webview/SimpleEncoreView.swift +49 -36
- package/examples/ios-webview/SimpleExample.swift +30 -86
- package/package.json +3 -7
- package/types/analytics/DiagnosticsOutbox.d.ts +22 -0
- package/types/analytics/DiagnosticsOutbox.d.ts.map +1 -0
- package/types/analytics/ReliableOutbox.d.ts +40 -0
- package/types/analytics/ReliableOutbox.d.ts.map +1 -0
- package/types/analytics/events.d.ts +100 -0
- package/types/analytics/events.d.ts.map +1 -1
- package/types/analytics/placementResolved.d.ts +150 -0
- package/types/analytics/placementResolved.d.ts.map +1 -0
- package/types/api/APIClient.d.ts +10 -2
- package/types/api/APIClient.d.ts.map +1 -1
- package/types/api/errorReportLimits.d.ts +50 -0
- package/types/api/errorReportLimits.d.ts.map +1 -0
- package/types/api/generated/types.d.ts +54 -7
- package/types/api/generated/types.d.ts.map +1 -1
- package/types/core/Configuration.d.ts +5 -0
- package/types/core/Configuration.d.ts.map +1 -1
- package/types/core/Encore.d.ts +61 -2
- package/types/core/Encore.d.ts.map +1 -1
- package/types/core/OfferManager.d.ts +29 -3
- package/types/core/OfferManager.d.ts.map +1 -1
- package/types/core/PlacementBuilder.d.ts +26 -2
- package/types/core/PlacementBuilder.d.ts.map +1 -1
- package/types/core/StrictUnlock.d.ts +20 -0
- package/types/core/StrictUnlock.d.ts.map +1 -0
- package/types/core/StrictUnlockReconciler.d.ts +94 -0
- package/types/core/StrictUnlockReconciler.d.ts.map +1 -0
- package/types/core/TransactionStore.d.ts +57 -13
- package/types/core/TransactionStore.d.ts.map +1 -1
- package/types/core/VerificationPoller.d.ts.map +1 -1
- package/types/core/claimBehavior.d.ts +28 -0
- package/types/core/claimBehavior.d.ts.map +1 -0
- package/types/core/errorContext.d.ts +18 -0
- package/types/core/errorContext.d.ts.map +1 -0
- package/types/core/errorType.d.ts +59 -0
- package/types/core/errorType.d.ts.map +1 -0
- package/types/core/hostDisplay.d.ts +50 -0
- package/types/core/hostDisplay.d.ts.map +1 -0
- package/types/core/useCase.d.ts +21 -0
- package/types/core/useCase.d.ts.map +1 -1
- package/types/core/version.d.ts +1 -1
- package/types/experiments/ExposureOutbox.d.ts +4 -28
- package/types/experiments/ExposureOutbox.d.ts.map +1 -1
- package/types/types.d.ts +188 -3
- package/types/types.d.ts.map +1 -1
- package/types/ui/OfferCard.d.ts +3 -1
- package/types/ui/OfferCard.d.ts.map +1 -1
- package/types/ui/OfferCarousel.d.ts +5 -0
- package/types/ui/OfferCarousel.d.ts.map +1 -1
- package/types/ui/OfferModal.d.ts +20 -0
- package/types/ui/OfferModal.d.ts.map +1 -1
- package/types/ui/PrimerScreen.d.ts +18 -11
- package/types/ui/PrimerScreen.d.ts.map +1 -1
- package/types/ui/RedemptionScreen.d.ts +15 -19
- package/types/ui/RedemptionScreen.d.ts.map +1 -1
- package/types/ui/RewardActions.d.ts +35 -0
- package/types/ui/RewardActions.d.ts.map +1 -1
- package/types/ui/appearance.d.ts +14 -0
- package/types/ui/appearance.d.ts.map +1 -1
- package/types/ui/brandComponents.d.ts.map +1 -1
- package/types/ui/styles.d.ts.map +1 -1
- package/types/utils/logger.d.ts +11 -1
- package/types/utils/logger.d.ts.map +1 -1
- package/embed/index.html +0 -57
- package/embed/styles.css +0 -154
- package/examples/ios-webview/EncoreWebViewBridge.swift +0 -419
- package/examples/ios-webview/ExampleViewController.swift +0 -233
|
@@ -1,114 +1,59 @@
|
|
|
1
1
|
//
|
|
2
2
|
// SimpleExample.swift
|
|
3
|
-
// Encore
|
|
3
|
+
// Encore hosted offer page, UIKit usage
|
|
4
4
|
//
|
|
5
|
-
// The simplest possible integration
|
|
5
|
+
// The simplest possible integration: build a URL, open it in a WKWebView.
|
|
6
|
+
//
|
|
7
|
+
// Requires `EncoreURLBuilder.swift`. The SwiftUI equivalent lives in
|
|
8
|
+
// `SimpleEncoreView.swift`.
|
|
6
9
|
//
|
|
7
10
|
|
|
8
11
|
import UIKit
|
|
9
12
|
import WebKit
|
|
10
13
|
|
|
11
|
-
class SimpleEncoreViewController: UIViewController {
|
|
12
|
-
|
|
14
|
+
final class SimpleEncoreViewController: UIViewController {
|
|
15
|
+
|
|
13
16
|
private var webView: WKWebView!
|
|
14
|
-
|
|
17
|
+
|
|
15
18
|
override func viewDidLoad() {
|
|
16
19
|
super.viewDidLoad()
|
|
17
|
-
|
|
18
|
-
// 1. Create
|
|
20
|
+
|
|
21
|
+
// 1. Create the webview.
|
|
19
22
|
webView = WKWebView(frame: view.bounds)
|
|
20
23
|
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
21
|
-
webView.backgroundColor = .clear
|
|
22
|
-
webView.isOpaque = false
|
|
23
24
|
view.addSubview(webView)
|
|
24
|
-
|
|
25
|
-
// 2. Build Encore URL
|
|
26
|
-
let url = EncoreURL.build(
|
|
27
|
-
apiKey: "your_api_key_here",
|
|
28
|
-
userId: "user_123",
|
|
29
|
-
environment: "production",
|
|
30
|
-
attributes: [
|
|
31
|
-
"email": "user@example.com",
|
|
32
|
-
"subscriptionTier": "free"
|
|
33
|
-
]
|
|
34
|
-
)!
|
|
35
|
-
|
|
36
|
-
// 3. Load it!
|
|
37
|
-
webView.load(URLRequest(url: url))
|
|
38
|
-
|
|
39
|
-
// That's it! The embed will auto-initialize and show offers.
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// MARK: - SwiftUI Version
|
|
44
|
-
|
|
45
|
-
import SwiftUI
|
|
46
25
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
apiKey: "
|
|
26
|
+
// 2. Build the URL. Only coarse targeting values belong here: the page
|
|
27
|
+
// refuses email, phone, names and precise location, and says so.
|
|
28
|
+
guard let url = EncoreURL.build(
|
|
29
|
+
apiKey: "pk_live_your_key_here",
|
|
51
30
|
userId: "user_123",
|
|
52
31
|
attributes: [
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
32
|
+
"subscriptionTier": "free",
|
|
33
|
+
"countryCode": "US",
|
|
34
|
+
],
|
|
35
|
+
custom: ["plan": "gold"]
|
|
36
|
+
) else { return }
|
|
59
37
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let environment: String
|
|
64
|
-
let attributes: [String: String]?
|
|
65
|
-
|
|
66
|
-
init(
|
|
67
|
-
apiKey: String,
|
|
68
|
-
userId: String? = nil,
|
|
69
|
-
environment: String = "production",
|
|
70
|
-
attributes: [String: String]? = nil
|
|
71
|
-
) {
|
|
72
|
-
self.apiKey = apiKey
|
|
73
|
-
self.userId = userId
|
|
74
|
-
self.environment = environment
|
|
75
|
-
self.attributes = attributes
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
func makeUIView(context: Context) -> WKWebView {
|
|
79
|
-
let webView = WKWebView()
|
|
80
|
-
webView.backgroundColor = .clear
|
|
81
|
-
webView.isOpaque = false
|
|
82
|
-
|
|
83
|
-
if let url = EncoreURL.build(
|
|
84
|
-
apiKey: apiKey,
|
|
85
|
-
userId: userId,
|
|
86
|
-
environment: environment,
|
|
87
|
-
attributes: attributes
|
|
88
|
-
) {
|
|
89
|
-
webView.load(URLRequest(url: url))
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return webView
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
func updateUIView(_ webView: WKWebView, context: Context) {
|
|
96
|
-
// No updates needed
|
|
38
|
+
// 3. Load it. Nothing else is required: no message handler to register,
|
|
39
|
+
// no bridge to install, no delegate to implement.
|
|
40
|
+
webView.load(URLRequest(url: url))
|
|
97
41
|
}
|
|
98
42
|
}
|
|
99
43
|
|
|
100
|
-
// MARK: -
|
|
44
|
+
// MARK: - Presentation patterns
|
|
101
45
|
|
|
102
46
|
extension SimpleEncoreViewController {
|
|
103
|
-
|
|
104
|
-
///
|
|
47
|
+
|
|
48
|
+
/// Present from a cancellation flow, where the churn carousel fits better
|
|
49
|
+
/// than the page's default reward sheet.
|
|
105
50
|
static func showInCancellationFlow(from viewController: UIViewController) {
|
|
106
51
|
let encoreVC = SimpleEncoreViewController()
|
|
107
52
|
encoreVC.modalPresentationStyle = .fullScreen
|
|
108
53
|
viewController.present(encoreVC, animated: true)
|
|
109
54
|
}
|
|
110
|
-
|
|
111
|
-
///
|
|
55
|
+
|
|
56
|
+
/// Present as a sheet.
|
|
112
57
|
static func showAsSheet(from viewController: UIViewController) {
|
|
113
58
|
let encoreVC = SimpleEncoreViewController()
|
|
114
59
|
if let sheet = encoreVC.sheetPresentationController {
|
|
@@ -117,8 +62,8 @@ extension SimpleEncoreViewController {
|
|
|
117
62
|
}
|
|
118
63
|
viewController.present(encoreVC, animated: true)
|
|
119
64
|
}
|
|
120
|
-
|
|
121
|
-
///
|
|
65
|
+
|
|
66
|
+
/// Embed in an existing view.
|
|
122
67
|
static func embedInView(_ containerView: UIView, parentVC: UIViewController) {
|
|
123
68
|
let encoreVC = SimpleEncoreViewController()
|
|
124
69
|
parentVC.addChild(encoreVC)
|
|
@@ -128,4 +73,3 @@ extension SimpleEncoreViewController {
|
|
|
128
73
|
encoreVC.didMove(toParent: parentVC)
|
|
129
74
|
}
|
|
130
75
|
}
|
|
131
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@encorekit/web-sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Encore SDK for web applications - display targeted offers and manage user entitlements",
|
|
6
6
|
"main": "./dist/cjs/index.cjs",
|
|
@@ -24,22 +24,19 @@
|
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
26
26
|
"types",
|
|
27
|
-
"embed/dist",
|
|
28
|
-
"embed/index.html",
|
|
29
|
-
"embed/styles.css",
|
|
30
27
|
"embed/README.md",
|
|
31
28
|
"examples",
|
|
32
29
|
"README.md",
|
|
33
30
|
"LICENSE"
|
|
34
31
|
],
|
|
35
32
|
"scripts": {
|
|
36
|
-
"build": "npm run build:types && npm run build:bundle
|
|
33
|
+
"build": "npm run build:types && npm run build:bundle",
|
|
37
34
|
"build:types": "tsc -p tsconfig.types.json --emitDeclarationOnly",
|
|
38
35
|
"build:bundle": "rollup -c",
|
|
39
|
-
"build:embed": "rollup -c --config-embed",
|
|
40
36
|
"build:watch": "rollup -c -w",
|
|
41
37
|
"test": "vitest run",
|
|
42
38
|
"test:watch": "vitest",
|
|
39
|
+
"verify:demo": "node scripts/verify-demo.mjs",
|
|
43
40
|
"typecheck": "tsc --noEmit -p tsconfig.build.json",
|
|
44
41
|
"lint": "eslint src --ext .ts,.tsx",
|
|
45
42
|
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
@@ -49,7 +46,6 @@
|
|
|
49
46
|
"demo:backend": "ENV_FILE=.env.local node demo/backend.js",
|
|
50
47
|
"demo:dev": "concurrently -n watch,backend,mock,frontend -c blue,magenta,yellow,green \"npm run build:watch\" \"npm run demo:backend\" \"npm run demo:mock\" \"npm run demo:frontend\"",
|
|
51
48
|
"dev:example": "bash scripts/dev-example.sh",
|
|
52
|
-
"embed:serve": "http-server -p 3001 -o embed/index.html",
|
|
53
49
|
"clean:examples": "bash scripts/clean-examples.sh",
|
|
54
50
|
"prepublishOnly": "npm test && npm run build && npm run clean:examples",
|
|
55
51
|
"pack:local": "npm run build && npm run clean:examples && npm pack",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reliable delivery for the `show()` choke-point diagnostics: `sdk_show_entered`,
|
|
3
|
+
* `sdk_show_aborted`, and the terminal `sdk_placement_resolved`.
|
|
4
|
+
*
|
|
5
|
+
* ONE outbox for all three, matching iOS, where every diagnostic goes through
|
|
6
|
+
* `Encore.shared.services.outbox` (`OfferSheetCoordinator.enqueueDiagnostic`).
|
|
7
|
+
* They share a delivery guarantee for the same reason: each one is the only
|
|
8
|
+
* evidence of an exit that produces no other event, so a row that only sometimes
|
|
9
|
+
* survives the tab closing is worse than none — the loss is invisible *and*
|
|
10
|
+
* biased toward the exits that close the page.
|
|
11
|
+
*
|
|
12
|
+
* Sharing one queue also means one set of page-lifecycle listeners for the whole
|
|
13
|
+
* diagnostic family rather than one per event type.
|
|
14
|
+
*
|
|
15
|
+
* See `ReliableOutbox` for the mechanism.
|
|
16
|
+
*/
|
|
17
|
+
import { ReliableOutbox } from './ReliableOutbox';
|
|
18
|
+
import type { StorageManager } from '../core/StorageManager';
|
|
19
|
+
export declare class DiagnosticsOutbox extends ReliableOutbox {
|
|
20
|
+
constructor(apiKey: string, analyticsBaseURL: string, storage: StorageManager);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=DiagnosticsOutbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiagnosticsOutbox.d.ts","sourceRoot":"","sources":["../../src/analytics/DiagnosticsOutbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D,qBAAa,iBAAkB,SAAQ,cAAc;gBACvC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc;CAG9E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reliable delivery for analytics events that must survive tab-close — unlike
|
|
3
|
+
* the fire-and-forget AnalyticsClient, this path is storage-backed and retried.
|
|
4
|
+
*
|
|
5
|
+
* Delivery primitive: `fetch(url, { keepalive: true })` — NOT `navigator.sendBeacon`.
|
|
6
|
+
* The ingest endpoint authenticates on the `X-Analytics-Key` request header, and
|
|
7
|
+
* sendBeacon cannot set headers (a beacon would arrive unauthenticated). keepalive
|
|
8
|
+
* fetch survives document unload like a beacon AND carries the auth header.
|
|
9
|
+
*
|
|
10
|
+
* Reliability model:
|
|
11
|
+
* - enqueue: persist the envelope, then keepalive-POST; remove on 2xx.
|
|
12
|
+
* - flush: replay every persisted envelope (on SDK init + on pagehide /
|
|
13
|
+
* visibilitychange:hidden) so a send that died with the tab retries.
|
|
14
|
+
* - envelopes carry a STABLE event_id → retries are idempotent backend-side.
|
|
15
|
+
* - an in-memory in-flight set avoids duplicate concurrent sends.
|
|
16
|
+
* - all storage / window / document access is SSR- and failure-guarded (fail-open).
|
|
17
|
+
*
|
|
18
|
+
* Extracted from ExposureOutbox, which was the first consumer of this pattern:
|
|
19
|
+
* every consumer gets its own instance (and its own storage key), so multiple
|
|
20
|
+
* ReliableOutbox instances bind independent lifecycle listeners — harmless
|
|
21
|
+
* duplication, not worth a shared coordinator for a small number of consumers.
|
|
22
|
+
*/
|
|
23
|
+
import type { AnalyticsEvent } from './models';
|
|
24
|
+
import type { StorageManager } from '../core/StorageManager';
|
|
25
|
+
export declare class ReliableOutbox {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(apiKey: string, analyticsBaseURL: string, storage: StorageManager, storageKey: string);
|
|
28
|
+
/**
|
|
29
|
+
* Persist an event and attempt delivery. `eventId` must be stable for a given
|
|
30
|
+
* (user, epoch) so retries de-duplicate backend-side. Returns whether the
|
|
31
|
+
* envelope durably landed in the configured storage tier: a quota-driven
|
|
32
|
+
* fallback-to-memory write is invisible to a fresh read, so the caller can avoid
|
|
33
|
+
* marking the epoch logged (and re-enqueue on the next trigger) instead of
|
|
34
|
+
* silently dropping the event.
|
|
35
|
+
*/
|
|
36
|
+
enqueue(event: AnalyticsEvent, eventId: string): boolean;
|
|
37
|
+
/** Replay every persisted envelope (init recovery + unload flush). */
|
|
38
|
+
flush(): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=ReliableOutbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReliableOutbox.d.ts","sourceRoot":"","sources":["../../src/analytics/ReliableOutbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,UAAU,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,qBAAa,cAAc;;gBAOb,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM;IAQjG;;;;;;;OAOG;IACH,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAaxD,sEAAsE;IACtE,KAAK,IAAI,IAAI;CAoDd"}
|
|
@@ -215,6 +215,106 @@ export declare function offerWebviewLoadFailed(distinctId: string, ctx: OfferEve
|
|
|
215
215
|
export declare function offerWebviewDismissed(distinctId: string, ctx: OfferEventContext, params: {
|
|
216
216
|
timeSpentSeconds: number;
|
|
217
217
|
}): AnalyticsEvent;
|
|
218
|
+
/**
|
|
219
|
+
* A strict-unlock claim confirmed by the advertiser's postback. Mirrors iOS
|
|
220
|
+
* `OfferVerifiedEvent`, including its two shapes: with the presentation context
|
|
221
|
+
* when the claim verified inside the session that made it, and with the
|
|
222
|
+
* transaction id ALONE when a later page load reconciled it.
|
|
223
|
+
*
|
|
224
|
+
* The context is optional for exactly that second case, and absent fields stay
|
|
225
|
+
* absent rather than being reconstructed — the same rule `OfferEventContext`
|
|
226
|
+
* states above. A reconciled claim genuinely has no impression or presentation in
|
|
227
|
+
* scope (the page that held them is gone), and `impression_id` is the warehouse's
|
|
228
|
+
* primary claim↔completion join key: a fabricated one joins against nothing while
|
|
229
|
+
* looking like coverage, where an absent one falls through to the documented
|
|
230
|
+
* `transaction_id` fallback and joins correctly.
|
|
231
|
+
*
|
|
232
|
+
* 🔴 `use_case` and `placement_id` are the exception, and they are NOT
|
|
233
|
+
* presentation-scoped. They describe the claim, which is the thing being verified, so
|
|
234
|
+
* they survive the page that made it — persisted on the pending record precisely so
|
|
235
|
+
* the reconciled shape can still carry them (`StrictUnlockReconciler.PendingClaim`,
|
|
236
|
+
* mirroring swift#123). Without them a strict-mode verification is the one conversion
|
|
237
|
+
* signal that falls outside every per-use-case and per-placement split, which is the
|
|
238
|
+
* comparison strict mode exists to be judged on. The bare shape is bare of
|
|
239
|
+
* PRESENTATION identity — `impression_id`, `presentation_id`, `variant_id` — not of
|
|
240
|
+
* every dimension.
|
|
241
|
+
*
|
|
242
|
+
* Only ever emitted in `unlockMode: 'strict'` — optimistic mode does no
|
|
243
|
+
* verification, so it has nothing to report.
|
|
244
|
+
*/
|
|
245
|
+
export declare function offerVerified(distinctId: string, params: {
|
|
246
|
+
transactionId: string;
|
|
247
|
+
useCase?: UseCase;
|
|
248
|
+
placementId?: string;
|
|
249
|
+
}, ctx?: OfferEventContext): AnalyticsEvent;
|
|
250
|
+
/**
|
|
251
|
+
* Why a `show()` exited before `sdk_offer_presentation_triggered` fired.
|
|
252
|
+
*
|
|
253
|
+
* The cross-SDK vocabulary, matching iOS's `ShowAbortReason` — not extended with
|
|
254
|
+
* web-only members. Two of web's pre-trigger exits (an invalid `useCase` value, a
|
|
255
|
+
* use case with no resolved copy) have no member here and therefore emit no
|
|
256
|
+
* `sdk_show_aborted`; both are fully described by `sdk_placement_resolved`'s
|
|
257
|
+
* `not_presented_reason`. Adding values to a frozen cross-SDK vocabulary is a
|
|
258
|
+
* cross-SDK decision, not a web one.
|
|
259
|
+
*
|
|
260
|
+
* `unsupported_os` exists on iOS and can never occur here — a browser that runs
|
|
261
|
+
* this bundle can render the sheet.
|
|
262
|
+
*/
|
|
263
|
+
export declare const ShowAbortReason: {
|
|
264
|
+
readonly NOT_CONFIGURED: "not_configured";
|
|
265
|
+
readonly ALREADY_PRESENTING: "already_presenting";
|
|
266
|
+
readonly EXPERIMENT_CONTROL: "experiment_control";
|
|
267
|
+
};
|
|
268
|
+
export type ShowAbortReasonValue = (typeof ShowAbortReason)[keyof typeof ShowAbortReason];
|
|
269
|
+
/**
|
|
270
|
+
* `show()` was called — emitted at the very top, before any gate.
|
|
271
|
+
*
|
|
272
|
+
* The only evidence the SDK was reached at all on an attempt that then exits
|
|
273
|
+
* somewhere with nothing else to say. `sdk_placement_resolved` covers every exit
|
|
274
|
+
* *after* configuration; this one is what makes "the host called `show()`"
|
|
275
|
+
* observable independently of what happened next.
|
|
276
|
+
*
|
|
277
|
+
* `layer` distinguishes the SDK that emitted it, since the React Native and
|
|
278
|
+
* Flutter bridges sit on top of this one and emit their own.
|
|
279
|
+
*
|
|
280
|
+
* No `variant_id`: at this point the SDK has not resolved which variant this
|
|
281
|
+
* attempt will render, and stamping the paywall's variant on what turns out to be
|
|
282
|
+
* a reward presentation is precisely the mis-attribution the per-use-case variant
|
|
283
|
+
* resolution exists to prevent.
|
|
284
|
+
*
|
|
285
|
+
* `use_case` IS known, however, because the caller asked for it, and it is stamped
|
|
286
|
+
* from the base property set rather than through the conditional `useCaseProperty`
|
|
287
|
+
* the offer-funnel events use. Required in the params type for the same reason: this
|
|
288
|
+
* dimension partitions a backend alarm (see `showAborted`), and a property that can
|
|
289
|
+
* be omitted eventually is.
|
|
290
|
+
*/
|
|
291
|
+
export declare function showEntered(distinctId: string, params: {
|
|
292
|
+
presentationId: string;
|
|
293
|
+
useCase: UseCase;
|
|
294
|
+
placementId?: string;
|
|
295
|
+
}): AnalyticsEvent;
|
|
296
|
+
/**
|
|
297
|
+
* A `show()` that exited at a pre-trigger gate. The taxonomy iOS draws and this
|
|
298
|
+
* mirrors: `sdk_show_aborted` means the attempt never entered the presentation
|
|
299
|
+
* funnel, `sdk_offer_presentation_failed` means it entered and did not reach
|
|
300
|
+
* presented.
|
|
301
|
+
*
|
|
302
|
+
* 🔴 `use_case` is REQUIRED and stamped from the base property set, never through the
|
|
303
|
+
* conditional `useCaseProperty`. Backend #443 counts `control_suppressions` off this
|
|
304
|
+
* event PARTITIONED BY use case, as the input to the D-6 bypass alarm — so a row
|
|
305
|
+
* without the dimension is not merely a thinner row, it is a suppression that lands
|
|
306
|
+
* in a NULL bucket and goes uncounted by the alarm it was supposed to feed. A
|
|
307
|
+
* conditional spread would make that the behaviour of whichever abort reason happened
|
|
308
|
+
* to be missing a use case; required-and-unconditional makes it unreachable. iOS
|
|
309
|
+
* (swift#123) and Android (android#55) stamp it the same way, off a non-optional enum.
|
|
310
|
+
*/
|
|
311
|
+
export declare function showAborted(distinctId: string, params: {
|
|
312
|
+
reason: ShowAbortReasonValue;
|
|
313
|
+
presentationId: string;
|
|
314
|
+
useCase: UseCase;
|
|
315
|
+
placementId?: string;
|
|
316
|
+
variantId?: string;
|
|
317
|
+
}): AnalyticsEvent;
|
|
218
318
|
/**
|
|
219
319
|
* The server-assigned variant landed and the sheet will render it.
|
|
220
320
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/analytics/events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAQxC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB;;;;CAI3B,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;;;;;CAMrB,CAAC;AA+BX;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGrF;AAMD,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,cAAc,CAMhB;AAED,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,cAAc,CAMhB;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/analytics/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sdk_placement_resolved` — the terminal record for one `show()` attempt, in
|
|
3
|
+
* iOS/Android's frozen outcome vocabulary (`PresentationResult.swift`).
|
|
4
|
+
*
|
|
5
|
+
* Exactly one row per attempt, whatever happened: not configured, use case not
|
|
6
|
+
* enabled, control cohort, no offers, claimed, dismissed, or blown up. That is the
|
|
7
|
+
* whole point of it — every OTHER event in the funnel exists only on the path that
|
|
8
|
+
* produces it, so a funnel built from them has no denominator that survives the
|
|
9
|
+
* early exits. Delivered through `DiagnosticsOutbox` (reliable, not
|
|
10
|
+
* fire-and-forget), and built from exactly one call site: `#recordPlacementResolved`
|
|
11
|
+
* in `Encore.ts`, which `show()`'s outer wrapper calls once.
|
|
12
|
+
*
|
|
13
|
+
* Two shape decisions worth stating up front, because both look like omissions:
|
|
14
|
+
*
|
|
15
|
+
* `advertiser_outcome` never carries `'verified'` on web. iOS's sheet blocks on the
|
|
16
|
+
* strict-unlock verification poll and can therefore fold the result into its terminal
|
|
17
|
+
* record; web's poll runs detached so it cannot race the modal's own close listeners
|
|
18
|
+
* (docs/architecture/platform-divergence/web.md #3). The fact is not lost — it is
|
|
19
|
+
* reported by `sdk_offer_verified`, joinable back on `presentation_id` in session or
|
|
20
|
+
* `transaction_id` across sessions. A cross-platform dashboard segmenting on
|
|
21
|
+
* `advertiser_outcome` alone will see web permanently at 0% verified; that is the
|
|
22
|
+
* documented shape, not a bug.
|
|
23
|
+
*
|
|
24
|
+
* `publisher_outcome` is REQUIRED and always `'not_attempted'`. The record reports
|
|
25
|
+
* what Encore did at the moment its flow ended, and Encore did not attempt a
|
|
26
|
+
* purchase — whether because web has no purchase controller at all, or because this
|
|
27
|
+
* particular flow did not use one, or because the use case is a reward. All three are
|
|
28
|
+
* the same observable fact here. Making it optional would smuggle in a second "does
|
|
29
|
+
* this platform even have the capability" dimension the record is not meant to carry.
|
|
30
|
+
*/
|
|
31
|
+
import type { AnalyticsEvent } from './models';
|
|
32
|
+
import type { ShowResult } from '../types';
|
|
33
|
+
import type { WireUseCase } from '../core/useCase';
|
|
34
|
+
/**
|
|
35
|
+
* NOT `'verified'` (see the file header). NOT `'cooldown'` either: the
|
|
36
|
+
* provisional-cooldown mechanism it describes is still unmerged backend-side, so a
|
|
37
|
+
* value for it would name something that cannot happen yet.
|
|
38
|
+
*/
|
|
39
|
+
export type AdvertiserOutcome = 'not_attempted' | 'claimed' | 'failed';
|
|
40
|
+
/** iOS/Android's wire values verbatim. Web emits only the first — see the header. */
|
|
41
|
+
export type PublisherOutcome = 'not_attempted' | 'purchased' | 'cancelled' | 'pending' | 'failed';
|
|
42
|
+
export type Resolution = 'not_presented' | 'presented';
|
|
43
|
+
export type NotPresentedReason =
|
|
44
|
+
/**
|
|
45
|
+
* Mapped from the `notConfigured` result, though no row can actually carry it:
|
|
46
|
+
* the outbox does not exist before configure(), so that path produces nothing to
|
|
47
|
+
* deliver. Mapped anyway so the translation is correct the day a diagnostic
|
|
48
|
+
* channel exists that early — iOS has the same blind spot, its enqueue being a
|
|
49
|
+
* no-op while services are nil.
|
|
50
|
+
*/
|
|
51
|
+
'not_configured' | 'already_presenting' | 'no_offer_available' | 'experiment_control' | 'use_case_unavailable'
|
|
52
|
+
/** `error.<ErrorCode>`, lowercased. */
|
|
53
|
+
| `error.${string}`;
|
|
54
|
+
export type Dismissal =
|
|
55
|
+
/** `userClosedModal` — the × and Escape. */
|
|
56
|
+
'close_button'
|
|
57
|
+
/**
|
|
58
|
+
* `userClickedOutside`. iOS's generic catch-all, not `swipe_dismiss`: that names a
|
|
59
|
+
* mobile gesture a browser backdrop tap is not.
|
|
60
|
+
*/
|
|
61
|
+
| 'dismissed'
|
|
62
|
+
/** `userDeclinedLastOffer`. */
|
|
63
|
+
| 'last_offer_declined'
|
|
64
|
+
/** A claim succeeded and the sheet closed itself. */
|
|
65
|
+
| 'flow_completed'
|
|
66
|
+
/** An unexpected failure after the sheet was already in play. */
|
|
67
|
+
| 'interrupted';
|
|
68
|
+
/**
|
|
69
|
+
* The three independent axes of a presented flow — iOS's
|
|
70
|
+
* `PresentationResult.Outcome` (`PresentationResult.swift:141`), field for field.
|
|
71
|
+
*
|
|
72
|
+
* All three are REQUIRED together. `'not_attempted'` is a real value meaning "the
|
|
73
|
+
* funnel was open and nothing entered it", which is a different fact from the axis
|
|
74
|
+
* being absent — and absent is not a state a presented row has. A row missing one
|
|
75
|
+
* of these is not a smaller row, it is an unreadable one: a dashboard cannot tell
|
|
76
|
+
* "nothing happened on this axis" from "the SDK forgot to say".
|
|
77
|
+
*/
|
|
78
|
+
export interface PresentedOutcome {
|
|
79
|
+
advertiserOutcome: AdvertiserOutcome;
|
|
80
|
+
/** Always `'not_attempted'` on web today — see the file header. */
|
|
81
|
+
publisherOutcome: PublisherOutcome;
|
|
82
|
+
dismissal: Dismissal;
|
|
83
|
+
}
|
|
84
|
+
/** Identity of what was claimed, carried only when the advertiser funnel got there. */
|
|
85
|
+
interface ClaimIdentity {
|
|
86
|
+
campaignId?: string;
|
|
87
|
+
offerId?: string;
|
|
88
|
+
transactionId?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The outcome half of the record, as a discriminated union rather than a bag of
|
|
92
|
+
* optionals — so the three-axis invariant is a compile error to break, not a
|
|
93
|
+
* convention to remember. Mirrors iOS's `enum PresentationResult { case
|
|
94
|
+
* notPresented(reason); case presented(Outcome) }`.
|
|
95
|
+
*
|
|
96
|
+
* The two branches share NO outcome fields: a `not_presented` row carries a reason
|
|
97
|
+
* and nothing else, exactly as iOS's wire assembly does
|
|
98
|
+
* (`OfferEvents+Outbox.swift:76-90`). Publishing `publisher_outcome:
|
|
99
|
+
* 'not_attempted'` on a row where no sheet ever appeared would be reporting on a
|
|
100
|
+
* funnel that never opened.
|
|
101
|
+
*/
|
|
102
|
+
export type PlacementOutcomeFields = {
|
|
103
|
+
resolution: 'not_presented';
|
|
104
|
+
notPresentedReason: NotPresentedReason;
|
|
105
|
+
} | ({
|
|
106
|
+
resolution: 'presented';
|
|
107
|
+
} & PresentedOutcome & ClaimIdentity);
|
|
108
|
+
/** The record's identity fields, present on every row regardless of resolution. */
|
|
109
|
+
export interface PlacementResolvedContext {
|
|
110
|
+
placementId?: string;
|
|
111
|
+
presentationId: string;
|
|
112
|
+
useCase: WireUseCase;
|
|
113
|
+
unlockMode: 'strict' | 'optimistic';
|
|
114
|
+
variantId?: string;
|
|
115
|
+
}
|
|
116
|
+
export type PlacementResolvedProperties = PlacementResolvedContext & PlacementOutcomeFields;
|
|
117
|
+
export declare function placementResolved(distinctId: string, properties: PlacementResolvedProperties): AnalyticsEvent;
|
|
118
|
+
/**
|
|
119
|
+
* What a resolving site must state explicitly, because the public `ShowResult`
|
|
120
|
+
* collapses it and no mapper can recover it:
|
|
121
|
+
*
|
|
122
|
+
* - `{status:'unavailable'}` is deliberately overloaded — no eligible offers, NCL
|
|
123
|
+
* control cohort, and use case not enabled all share it, so an integrator cannot
|
|
124
|
+
* reverse-engineer the incrementality experiment from a return value. The record
|
|
125
|
+
* still needs to tell them apart.
|
|
126
|
+
* - `UNKNOWN_ERROR` is produced by three structurally different sites: a failure
|
|
127
|
+
* before the sheet ever rendered, a rendering failure with no claim attempted, and
|
|
128
|
+
* a claim whose transaction write failed. The code alone cannot distinguish them.
|
|
129
|
+
*
|
|
130
|
+
* Every other case — a claim, a string `NotGrantedReason`, a distinctly-coded error —
|
|
131
|
+
* is fully derivable, and an override for those is unnecessary though harmless: it
|
|
132
|
+
* always wins.
|
|
133
|
+
*/
|
|
134
|
+
export interface PlacementResolutionOverride {
|
|
135
|
+
notPresentedReason?: NotPresentedReason;
|
|
136
|
+
advertiserOutcome?: AdvertiserOutcome;
|
|
137
|
+
dismissal?: Dismissal;
|
|
138
|
+
}
|
|
139
|
+
export type DerivedPlacementResolvedFields = PlacementOutcomeFields;
|
|
140
|
+
/**
|
|
141
|
+
* Pure mapper: a `ShowResult` (plus a disambiguating override where the result
|
|
142
|
+
* collapses one) to the record's outcome fields.
|
|
143
|
+
*
|
|
144
|
+
* `ShowResult`'s claimed member already carries `campaignId`/`offerId`/
|
|
145
|
+
* `transactionId` inline, so nothing else has to be threaded here to identify what
|
|
146
|
+
* was claimed.
|
|
147
|
+
*/
|
|
148
|
+
export declare function deriveResolvedFields(result: ShowResult, override?: PlacementResolutionOverride): DerivedPlacementResolvedFields;
|
|
149
|
+
export {};
|
|
150
|
+
//# sourceMappingURL=placementResolved.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"placementResolved.d.ts","sourceRoot":"","sources":["../../src/analytics/placementResolved.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAA+B,UAAU,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvE,qFAAqF;AACrF,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElG,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,WAAW,CAAC;AAEvD,MAAM,MAAM,kBAAkB;AAC5B;;;;;;GAMG;AACD,gBAAgB,GAChB,oBAAoB,GACpB,oBAAoB,GACpB,oBAAoB,GACpB,sBAAsB;AACxB,uCAAuC;GACrC,SAAS,MAAM,EAAE,CAAC;AAEtB,MAAM,MAAM,SAAS;AACnB,4CAA4C;AAC1C,cAAc;AAChB;;;GAGG;GACD,WAAW;AACb,+BAA+B;GAC7B,qBAAqB;AACvB,qDAAqD;GACnD,gBAAgB;AAClB,iEAAiE;GAC/D,aAAa,CAAC;AAElB;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,mEAAmE;IACnE,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,uFAAuF;AACvF,UAAU,aAAa;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,sBAAsB,GAC9B;IAAE,UAAU,EAAE,eAAe,CAAC;IAAC,kBAAkB,EAAE,kBAAkB,CAAA;CAAE,GACvE,CAAC;IAAE,UAAU,EAAE,WAAW,CAAA;CAAE,GAAG,gBAAgB,GAAG,aAAa,CAAC,CAAC;AAErE,mFAAmF;AACnF,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,QAAQ,GAAG,YAAY,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,GAAG,sBAAsB,CAAC;AAE5F,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,2BAA2B,GACtC,cAAc,CAchB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,2BAA2B;IAC1C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAYD,MAAM,MAAM,8BAA8B,GAAG,sBAAsB,CAAC;AAsBpE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,UAAU,EAClB,QAAQ,CAAC,EAAE,2BAA2B,GACrC,8BAA8B,CAyEhC"}
|
package/types/api/APIClient.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { UserAttributes, Entitlement, VerificationStatus, UseCase } from '../types';
|
|
7
7
|
import type { StartTransactionResponse, InitUserResponse, IdentifyUserResponse, RemoteConfigResponse, OfferModel, BackendVerificationStatus } from './models';
|
|
8
|
+
import type { ErrorContext } from '../core/errorContext';
|
|
8
9
|
interface RequestOptions {
|
|
9
10
|
method: 'GET' | 'POST' | 'PATCH';
|
|
10
11
|
headers?: Record<string, string>;
|
|
@@ -46,8 +47,14 @@ export declare class APIClient {
|
|
|
46
47
|
* turn this best-effort label into a hard failure of the entire offers fetch for
|
|
47
48
|
* a publisher who simply named their placement something long. Truncating keeps
|
|
48
49
|
* the analytics label degraded-but-present instead of losing the offer entirely.
|
|
50
|
+
*
|
|
51
|
+
* `maxPostbackTimeMs` is strict-unlock mode's offer filter — only campaigns whose
|
|
52
|
+
* postback latency fits the verification window. It is a fixed SDK constant
|
|
53
|
+
* (`StrictUnlock.MAX_POSTBACK_TIME_MS`), never publisher input, so unlike
|
|
54
|
+
* `placementId` there is nothing to bound here: the contract's own 1000..120000
|
|
55
|
+
* range (`offers/dto.ts`) cannot be violated by a caller.
|
|
49
56
|
*/
|
|
50
|
-
fetchOffers(userId: string, attributes: UserAttributes, placementId?: string): Promise<{
|
|
57
|
+
fetchOffers(userId: string, attributes: UserAttributes, placementId?: string, maxPostbackTimeMs?: number): Promise<{
|
|
51
58
|
offers: OfferModel[];
|
|
52
59
|
}>;
|
|
53
60
|
/**
|
|
@@ -113,7 +120,8 @@ export declare class APIClient {
|
|
|
113
120
|
reportError(params: {
|
|
114
121
|
errorType: string;
|
|
115
122
|
message: string;
|
|
116
|
-
context
|
|
123
|
+
/** Typed so the backend's `[errorType, context]` fingerprint groups with iOS and Android. */
|
|
124
|
+
context: ErrorContext;
|
|
117
125
|
severity?: 'fatal' | 'error' | 'warning' | 'info';
|
|
118
126
|
stackTrace?: string;
|
|
119
127
|
userId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"APIClient.d.ts","sourceRoot":"","sources":["../../src/api/APIClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAe,cAAc,EAAE,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEtG,OAAO,KAAK,EAEV,wBAAwB,EAIxB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,UAAU,EACV,yBAAyB,EAC1B,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"APIClient.d.ts","sourceRoot":"","sources":["../../src/api/APIClient.ts"],"names":[],"mappings":"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"}
|