@guidelytech/sdk-core 0.6.1 → 0.7.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 +21 -0
- package/README.md +29 -4
- package/dist/headless.d.cts +2 -1
- package/dist/headless.d.ts +2 -1
- package/dist/index.cjs +101 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +101 -2
- package/dist/index.js.map +1 -1
- package/dist/types-DbKQPvFt.d.cts +238 -0
- package/dist/types-DqhNl5Am.d.ts +238 -0
- package/package.json +4 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Guidely
|
|
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
CHANGED
|
@@ -51,6 +51,7 @@ The module is safe to import during SSR (nothing touches `window` at module scop
|
|
|
51
51
|
| `user` | — | `{ id, traits?, account? }` to identify immediately. |
|
|
52
52
|
| `fetch` | global | Custom `fetch` (tests, polyfills). |
|
|
53
53
|
| `disableAuthoring` | `false` | Ignore `?guidely_authoring=` in the URL. |
|
|
54
|
+
| `flags` | on | Feature flags (same key and API URL). `false` turns them off; an object passes [flags client options](../flags/README.md#options), e.g. `{ payload }` (server-rendered bootstrap), `{ attributes }`, `{ remoteEval: true }`, `{ pollingMode: "stream" }`. |
|
|
54
55
|
|
|
55
56
|
## API
|
|
56
57
|
|
|
@@ -86,6 +87,10 @@ event, never thrown into the host application.
|
|
|
86
87
|
| `getState()` | Debug snapshot: ready flag, ids, config version, active/queued guides, widgets, state, pending events. |
|
|
87
88
|
| `destroy()` | Full cleanup: guides, widgets, listeners, timers, the `#guidely-root` host; flushes pending events via `sendBeacon`. A new client can be created afterwards. |
|
|
88
89
|
| `GuidelyClient.init(options)` / `GuidelyClient.get()` | Singleton helpers used by the embed (`window.Guidely.init/get`). |
|
|
90
|
+
| `isFeatureEnabled(key, fallback = false)` | Boolean flag for the current user (`fallback` until loaded, when missing or not a boolean). |
|
|
91
|
+
| `getFeatureValue(key, fallback)` / `getFeatureDetails(key, fallback)` | Flag value / value plus reason, rule, variation and experiment. |
|
|
92
|
+
| `onFlagsChange(cb): () => void` | Called whenever flag values may have changed (new rules, identify, navigation, overrides). |
|
|
93
|
+
| `flags` | The [flags client](../flags/README.md): `isEnabled`, `getValue`, `getAll`, `setAttributes`, `setOverrides`, `ready`, `subscribe`… |
|
|
89
94
|
|
|
90
95
|
### Events
|
|
91
96
|
|
|
@@ -93,7 +98,26 @@ event, never thrown into the host application.
|
|
|
93
98
|
`guide:complete(guide)`, `guide:dismiss(guide)`, `guide:skip(guide)`,
|
|
94
99
|
`checklist:task({ guide, task, progress })`, `checklist:complete(guide)`,
|
|
95
100
|
`survey:submit({ guide, answers, responseId })`, `resource-center:open()`, `error(Error)`,
|
|
96
|
-
`track(sdkEvent)`, `identify({ userId, anonymousId })`, `authoring({ active })
|
|
101
|
+
`track(sdkEvent)`, `identify({ userId, anonymousId })`, `authoring({ active })`, `flags:ready()`,
|
|
102
|
+
`flags:change()`.
|
|
103
|
+
|
|
104
|
+
## Feature flags
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
if (guidely.isFeatureEnabled("new-checkout")) showNewCheckout();
|
|
108
|
+
const color = guidely.getFeatureValue("checkout-button-color", "blue");
|
|
109
|
+
guidely.onFlagsChange(() => rerender());
|
|
110
|
+
guidely.flags.updateAttributes({ cohort: "beta" }); // extra attributes, kept across identify()
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Flags load in parallel with the guide config, with the same public key, and the last payload is
|
|
114
|
+
cached in storage (`guidely:flags:<key>`). Attributes are maintained for you: `id` (the identified
|
|
115
|
+
user id, else the anonymous id), `anonymousId`, every identify trait, `account` (`{ id, …traits }`),
|
|
116
|
+
`$audiences` (audience ids from identify), `url`, `path`, `deviceType`, `browser`, `os`, `locale`,
|
|
117
|
+
`environment` and `platform: "web"`; they update on `identify`, `updateTraits`, `setAccount`,
|
|
118
|
+
`reset` and navigation. Experiment exposures are tracked as `experiment_viewed` events
|
|
119
|
+
(`experimentKey`, `variationId`, `variationName`, `flagKey`, `hashAttribute`) once per session,
|
|
120
|
+
through the event queue, so consent and `analytics: false` apply.
|
|
97
121
|
|
|
98
122
|
## Behaviour
|
|
99
123
|
|
|
@@ -147,7 +171,7 @@ Messages posted to the opener: `guidely:authoring-ready { sessionId, url }`, `gu
|
|
|
147
171
|
## Storage keys
|
|
148
172
|
|
|
149
173
|
`guidely:anon`, `guidely:seen`, `guidely:config:<key>`, `guidely:etag:<key>`, `guidely:state:<key>`,
|
|
150
|
-
`guidely:user:<key>`, `guidely:queue:<key>` (local/session storage per `storage` option);
|
|
174
|
+
`guidely:user:<key>`, `guidely:queue:<key>`, `guidely:flags:<key>` (local/session storage per `storage` option);
|
|
151
175
|
`guidely:session`, `guidely:active`, `guidely:authoring` (sessionStorage).
|
|
152
176
|
|
|
153
177
|
## Network recording (session replay)
|
|
@@ -181,11 +205,12 @@ lazily loaded recorder chunk; the base bundle does not grow.
|
|
|
181
205
|
|
|
182
206
|
| Bundle | minified | min+gz |
|
|
183
207
|
|---|---|---|
|
|
184
|
-
| sdk-core + guide-runtime + floating-ui + `@guidelytech/
|
|
208
|
+
| sdk-core + guide-runtime + floating-ui + `@guidelytech/flags` (everything an app ships, excluding `@guidelytech/shared`) | 195 kB | **61.4 kB** |
|
|
185
209
|
| Scout messenger chunk (`@guidelytech/guide-runtime/messenger`, loaded on demand) | 26 kB | 8.8 kB |
|
|
186
210
|
| Session-replay chunk (`./recorder`: rrweb + replay controller + network recording, loaded only when a session is recorded) | 94 kB | 30 kB |
|
|
187
211
|
| script-tag build `guidely.js` (authoring schemas and messenger inlined) | 244 kB | ~71 kB |
|
|
188
212
|
|
|
189
213
|
The SDK imports only the zod-free `@guidelytech/shared/runtime` entry; the Zod schemas are loaded
|
|
190
|
-
lazily and only when the page enters authoring mode.
|
|
214
|
+
lazily and only when the page enters authoring mode. Feature flags (client + evaluator) add
|
|
215
|
+
~13 kB min+gz. Budget: 45 kB min+gz for the npm runtime and
|
|
191
216
|
15 kB for the messenger chunk, 80 kB for the session-replay chunk.
|
package/dist/headless.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { A as Api, a as ApiResponse, F as FetchLike, K as KEYS, b as KeyValueStore, c as backoffMs, m as memoryStore, p as postWithRetry, r as readJson, s as sleep, w as writeJson } from './http-47tiAlOM.cjs';
|
|
2
|
-
export { C as ChecklistProgressState, a as ConsentState, E as EventQueue, b as EventQueueOptions, G as GuideLocalState, c as GuidelyAccount, d as GuidelyEnvironment, e as GuidelyUser, P as PersistedState, S as SessionState, f as areMutuallyExclusive, i as isExclusiveGuide, g as isFrequencyEligible, h as isWithinSchedule } from './types-
|
|
2
|
+
export { C as ChecklistProgressState, a as ConsentState, E as EventQueue, b as EventQueueOptions, G as GuideLocalState, c as GuidelyAccount, d as GuidelyEnvironment, e as GuidelyUser, P as PersistedState, S as SessionState, f as areMutuallyExclusive, i as isExclusiveGuide, g as isFrequencyEligible, h as isWithinSchedule } from './types-DbKQPvFt.cjs';
|
|
3
3
|
import '@guidelytech/shared';
|
|
4
|
+
import '@guidelytech/flags';
|
|
4
5
|
|
|
5
6
|
type AnyFn = (...args: any[]) => void;
|
|
6
7
|
/** Tiny typed event emitter. Listener errors are reported, never thrown into the caller. */
|
package/dist/headless.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { A as Api, a as ApiResponse, F as FetchLike, K as KEYS, b as KeyValueStore, c as backoffMs, m as memoryStore, p as postWithRetry, r as readJson, s as sleep, w as writeJson } from './http-47tiAlOM.js';
|
|
2
|
-
export { C as ChecklistProgressState, a as ConsentState, E as EventQueue, b as EventQueueOptions, G as GuideLocalState, c as GuidelyAccount, d as GuidelyEnvironment, e as GuidelyUser, P as PersistedState, S as SessionState, f as areMutuallyExclusive, i as isExclusiveGuide, g as isFrequencyEligible, h as isWithinSchedule } from './types-
|
|
2
|
+
export { C as ChecklistProgressState, a as ConsentState, E as EventQueue, b as EventQueueOptions, G as GuideLocalState, c as GuidelyAccount, d as GuidelyEnvironment, e as GuidelyUser, P as PersistedState, S as SessionState, f as areMutuallyExclusive, i as isExclusiveGuide, g as isFrequencyEligible, h as isWithinSchedule } from './types-DqhNl5Am.js';
|
|
3
3
|
import '@guidelytech/shared';
|
|
4
|
+
import '@guidelytech/flags';
|
|
4
5
|
|
|
5
6
|
type AnyFn = (...args: any[]) => void;
|
|
6
7
|
/** Tiny typed event emitter. Listener errors are reported, never thrown into the caller. */
|
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
60
60
|
var import_runtime13 = require("@guidelytech/shared/runtime");
|
|
61
61
|
var import_guide_runtime4 = require("@guidelytech/guide-runtime");
|
|
62
62
|
var import_guide_runtime5 = require("@guidelytech/guide-runtime");
|
|
63
|
+
var import_flags = require("@guidelytech/flags");
|
|
63
64
|
|
|
64
65
|
// src/authoring.ts
|
|
65
66
|
var import_guide_runtime = require("@guidelytech/guide-runtime");
|
|
@@ -1456,7 +1457,7 @@ var loadRecorder = async () => (await import("./recorder.cjs")).recorder;
|
|
|
1456
1457
|
|
|
1457
1458
|
// src/client.ts
|
|
1458
1459
|
var SDK_NAME = "@guidelytech/sdk-core";
|
|
1459
|
-
var SDK_VERSION = "0.
|
|
1460
|
+
var SDK_VERSION = "0.7.0";
|
|
1460
1461
|
var DEFAULT_API_URL = "https://api.guidely.app";
|
|
1461
1462
|
var PAGE_SCOPED = /* @__PURE__ */ new Set(["page_load", "url_match", "element_click", "element_visible", "delay"]);
|
|
1462
1463
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -1526,6 +1527,10 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1526
1527
|
__publicField(this, "initialPageViewSent", false);
|
|
1527
1528
|
__publicField(this, "pageViewUrl", null);
|
|
1528
1529
|
__publicField(this, "pageLeft", false);
|
|
1530
|
+
/** Feature flags for this environment: `guidely.flags.isEnabled("new-checkout")`. */
|
|
1531
|
+
__publicField(this, "flags");
|
|
1532
|
+
/** Experiments already reported this session (`experiment_viewed` is sent once per session). */
|
|
1533
|
+
__publicField(this, "exposures", /* @__PURE__ */ new Set());
|
|
1529
1534
|
__publicField(this, "customListeners", /* @__PURE__ */ new Map());
|
|
1530
1535
|
__publicField(this, "eventBus", {
|
|
1531
1536
|
on: (name, cb) => {
|
|
@@ -1584,6 +1589,39 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1584
1589
|
onError: (err) => this.reportError(err)
|
|
1585
1590
|
});
|
|
1586
1591
|
if (options.user) this.user = { ...options.user };
|
|
1592
|
+
this.flags = this.createFlags(options.flags);
|
|
1593
|
+
}
|
|
1594
|
+
createFlags(opts) {
|
|
1595
|
+
const base = { sdkKey: this.options.projectId, apiUrl: this.options.apiUrl, fetch: this.options.fetch, sdk: { name: SDK_NAME, version: SDK_VERSION } };
|
|
1596
|
+
if (opts === false) return (0, import_flags.createFlagsClient)({ ...base, overrideBehaviour: "localOnly", offline: true, reportUsage: false, trackExposures: false, storage: false, logger: null });
|
|
1597
|
+
const o = opts ?? {};
|
|
1598
|
+
return (0, import_flags.createFlagsClient)({
|
|
1599
|
+
...base,
|
|
1600
|
+
storage: { getItem: (k) => this.store.get(k), setItem: (k, v) => this.store.set(k, v), removeItem: (k) => this.store.remove(k) },
|
|
1601
|
+
reportUsage: this.options.analytics,
|
|
1602
|
+
// Failures surface through onError (and `debug` logs); development warnings (unknown flag keys) reach the console.
|
|
1603
|
+
logger: { warn: (...a) => console.warn("[Guidely]", ...a), error: (...a) => this.log(...a) },
|
|
1604
|
+
...o,
|
|
1605
|
+
contextAttributes: this.flagContext(),
|
|
1606
|
+
// Exposures travel through the event pipeline (with the session) as `experiment_viewed`.
|
|
1607
|
+
trackExposures: false,
|
|
1608
|
+
onFlagEvaluated: (result) => {
|
|
1609
|
+
this.trackExposure(result);
|
|
1610
|
+
o.onFlagEvaluated?.(result);
|
|
1611
|
+
},
|
|
1612
|
+
onReady: () => {
|
|
1613
|
+
this.emitter.emit("flags:ready");
|
|
1614
|
+
o.onReady?.();
|
|
1615
|
+
},
|
|
1616
|
+
onChange: (data) => {
|
|
1617
|
+
this.emitter.emit("flags:change");
|
|
1618
|
+
o.onChange?.(data);
|
|
1619
|
+
},
|
|
1620
|
+
onError: (err) => {
|
|
1621
|
+
this.reportError(err);
|
|
1622
|
+
o.onError?.(err);
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1587
1625
|
}
|
|
1588
1626
|
// ---------------------------------------------------------------------------
|
|
1589
1627
|
// Lifecycle
|
|
@@ -1784,6 +1822,7 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1784
1822
|
this.replay = null;
|
|
1785
1823
|
this.queue.flushSync();
|
|
1786
1824
|
this.queue.destroy();
|
|
1825
|
+
this.flags.destroy();
|
|
1787
1826
|
this.emitter.clear();
|
|
1788
1827
|
(0, import_guide_runtime4.destroyHost)();
|
|
1789
1828
|
if (current === this) current = null;
|
|
@@ -1797,6 +1836,7 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1797
1836
|
this.identitySettled = true;
|
|
1798
1837
|
this.user = { id: String(userId), traits: { ...this.user?.id === String(userId) ? this.user.traits : {}, ...traits || {} }, account: account ?? (this.user?.id === String(userId) ? this.user.account : void 0) };
|
|
1799
1838
|
writeJson(this.store, KEYS.user(this.options.projectId), this.user);
|
|
1839
|
+
this.syncFlagAttributes();
|
|
1800
1840
|
this.enqueue("identify", { properties: { traits: (0, import_runtime13.sanitizeProperties)(this.user.traits) } });
|
|
1801
1841
|
await this.syncIdentify();
|
|
1802
1842
|
this.emitter.emit("identify", { userId: this.user.id, anonymousId: this.anonymousId });
|
|
@@ -1837,6 +1877,7 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1837
1877
|
};
|
|
1838
1878
|
if (data.firstSeenAt && Date.now() - Date.parse(data.firstSeenAt) > 6e4) this.firstVisit = false;
|
|
1839
1879
|
this.persistState();
|
|
1880
|
+
this.syncFlagAttributes();
|
|
1840
1881
|
this.widgets.forEach((w, id) => {
|
|
1841
1882
|
const g = this.findGuide(id);
|
|
1842
1883
|
if (w.checklist && g) w.checklist.setProgress(this.getChecklistProgress(g.id));
|
|
@@ -1848,6 +1889,7 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1848
1889
|
if (!this.user) {
|
|
1849
1890
|
this.user = { id: "", account };
|
|
1850
1891
|
writeJson(this.store, KEYS.user(this.options.projectId), this.user);
|
|
1892
|
+
this.syncFlagAttributes();
|
|
1851
1893
|
return;
|
|
1852
1894
|
}
|
|
1853
1895
|
await this.identify(this.user.id, void 0, account);
|
|
@@ -1856,6 +1898,7 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1856
1898
|
async updateTraits(traits) {
|
|
1857
1899
|
if (!this.user?.id) {
|
|
1858
1900
|
this.user = { id: "", traits: { ...this.user?.traits || {}, ...traits } };
|
|
1901
|
+
this.syncFlagAttributes();
|
|
1859
1902
|
return;
|
|
1860
1903
|
}
|
|
1861
1904
|
await this.identify(this.user.id, traits, this.user.account);
|
|
@@ -1881,6 +1924,8 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1881
1924
|
this.widgets.clear();
|
|
1882
1925
|
forgetConversations(this.store, this.options.projectId);
|
|
1883
1926
|
this.destroyMessenger();
|
|
1927
|
+
this.exposures.clear();
|
|
1928
|
+
this.syncFlagAttributes();
|
|
1884
1929
|
this.emitter.emit("identify", { userId: null, anonymousId: this.anonymousId });
|
|
1885
1930
|
if (this.isReady) {
|
|
1886
1931
|
this.renderPersistentWidgets();
|
|
@@ -1953,6 +1998,7 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
1953
1998
|
if (this.destroyed) return;
|
|
1954
1999
|
const changed = url !== this.lastUrl;
|
|
1955
2000
|
this.lastUrl = url;
|
|
2001
|
+
if (changed) this.syncFlagAttributes();
|
|
1956
2002
|
if (!explicit && changed) {
|
|
1957
2003
|
this.leavePage(url);
|
|
1958
2004
|
this.trackPageView(url);
|
|
@@ -2884,6 +2930,58 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
2884
2930
|
if (!this.config?.messenger?.enabled) return;
|
|
2885
2931
|
void this.loadMessenger().then((m) => m?.showNewMessage(text));
|
|
2886
2932
|
}
|
|
2933
|
+
// ---------------------------------------------------------------------------
|
|
2934
|
+
// Feature flags
|
|
2935
|
+
// ---------------------------------------------------------------------------
|
|
2936
|
+
/** Boolean flag value for the current user; `fallback` (default `false`) until loaded or when missing. */
|
|
2937
|
+
isFeatureEnabled(key, fallback = false) {
|
|
2938
|
+
return this.flags.isEnabled(key, fallback);
|
|
2939
|
+
}
|
|
2940
|
+
/** Flag value for the current user; `fallback` when missing or of a different type. */
|
|
2941
|
+
getFeatureValue(key, fallback) {
|
|
2942
|
+
return this.flags.getValue(key, fallback);
|
|
2943
|
+
}
|
|
2944
|
+
/** Flag value plus why it was served (reason, rule, variation, experiment). */
|
|
2945
|
+
getFeatureDetails(key, fallback) {
|
|
2946
|
+
return this.flags.getDetails(key, fallback);
|
|
2947
|
+
}
|
|
2948
|
+
/** Calls `cb` whenever flag values may have changed (new rules, identity, page, overrides). Returns an unsubscribe function. */
|
|
2949
|
+
onFlagsChange(cb) {
|
|
2950
|
+
return this.flags.subscribe(cb);
|
|
2951
|
+
}
|
|
2952
|
+
/** Attributes flags are evaluated with: identity, traits, account, audiences, page and device. */
|
|
2953
|
+
flagContext() {
|
|
2954
|
+
const device = detectDevice(navigator.userAgent, window.innerWidth);
|
|
2955
|
+
const account = this.user?.account;
|
|
2956
|
+
return {
|
|
2957
|
+
url: location.href,
|
|
2958
|
+
path: location.pathname,
|
|
2959
|
+
deviceType: device.type,
|
|
2960
|
+
browser: device.browser,
|
|
2961
|
+
os: device.os,
|
|
2962
|
+
locale: navigator.language || void 0,
|
|
2963
|
+
environment: this.options.environment,
|
|
2964
|
+
platform: "web",
|
|
2965
|
+
...this.user?.traits ?? {},
|
|
2966
|
+
id: this.user?.id || this.anonymousId,
|
|
2967
|
+
anonymousId: this.anonymousId,
|
|
2968
|
+
account: account ? { ...account.traits ?? {}, id: account.id } : void 0,
|
|
2969
|
+
$audiences: [...this.state.audienceIds]
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
syncFlagAttributes() {
|
|
2973
|
+
if (!this.destroyed) this.flags?.setContextAttributes(this.flagContext());
|
|
2974
|
+
}
|
|
2975
|
+
/** `experiment_viewed`, once per session and assignment, through the event queue (consent applies). */
|
|
2976
|
+
trackExposure(result) {
|
|
2977
|
+
const exp = result.inExperiment ? result.experiment : void 0;
|
|
2978
|
+
if (!exp || this.destroyed) return;
|
|
2979
|
+
const key = `${this.session.id}|${exp.key}|${exp.hashValue}|${exp.variationId}`;
|
|
2980
|
+
if (this.exposures.has(key)) return;
|
|
2981
|
+
if (this.exposures.size > 500) this.exposures.clear();
|
|
2982
|
+
this.exposures.add(key);
|
|
2983
|
+
this.enqueue("experiment_viewed", { properties: { experimentKey: exp.key, variationId: exp.variationId, flagKey: result.key, hashAttribute: exp.hashAttribute, ...exp.variationName ? { variationName: exp.variationName } : {} } });
|
|
2984
|
+
}
|
|
2887
2985
|
on(event, cb) {
|
|
2888
2986
|
return this.emitter.on(event, cb);
|
|
2889
2987
|
}
|
|
@@ -2909,7 +3007,8 @@ var GuidelyClient = class _GuidelyClient {
|
|
|
2909
3007
|
session: this.session,
|
|
2910
3008
|
pendingEvents: this.queue.size,
|
|
2911
3009
|
authoring: !!this.authoring?.isActive(),
|
|
2912
|
-
capture: !!this.capture?.isActive()
|
|
3010
|
+
capture: !!this.capture?.isActive(),
|
|
3011
|
+
flagsReady: this.flags.isReady()
|
|
2913
3012
|
};
|
|
2914
3013
|
}
|
|
2915
3014
|
// ---------------------------------------------------------------------------
|