posthog-js-lite 3.1.0 → 3.2.1

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/lib/index.d.ts CHANGED
@@ -48,6 +48,8 @@ declare enum PostHogPersistedProperty {
48
48
  Props = "props",
49
49
  FeatureFlags = "feature_flags",
50
50
  FeatureFlagPayloads = "feature_flag_payloads",
51
+ BootstrapFeatureFlags = "bootstrap_feature_flags",
52
+ BootstrapFeatureFlagPayloads = "bootstrap_feature_flag_payloads",
51
53
  OverrideFeatureFlags = "override_feature_flags",
52
54
  Queue = "queue",
53
55
  OptedOut = "opted_out",
@@ -57,7 +59,8 @@ declare enum PostHogPersistedProperty {
57
59
  GroupProperties = "group_properties",
58
60
  InstalledAppBuild = "installed_app_build",
59
61
  InstalledAppVersion = "installed_app_version",
60
- SessionReplay = "session_replay"
62
+ SessionReplay = "session_replay",
63
+ DecideEndpointWasHit = "decide_endpoint_was_hit"
61
64
  }
62
65
  type PostHogFetchOptions = {
63
66
  method: 'GET' | 'POST' | 'PUT' | 'PATCH';
@@ -327,6 +330,7 @@ declare class PostHog extends PostHogCore {
327
330
  private _storageCache;
328
331
  private _storageKey;
329
332
  constructor(apiKey: string, options?: PostHogOptions);
333
+ private getWindow;
330
334
  getPersistedProperty<T>(key: PostHogPersistedProperty): T | undefined;
331
335
  setPersistedProperty<T>(key: PostHogPersistedProperty, value: T | null): void;
332
336
  fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
package/lib/index.esm.js CHANGED
@@ -5,6 +5,8 @@ var PostHogPersistedProperty;
5
5
  PostHogPersistedProperty["Props"] = "props";
6
6
  PostHogPersistedProperty["FeatureFlags"] = "feature_flags";
7
7
  PostHogPersistedProperty["FeatureFlagPayloads"] = "feature_flag_payloads";
8
+ PostHogPersistedProperty["BootstrapFeatureFlags"] = "bootstrap_feature_flags";
9
+ PostHogPersistedProperty["BootstrapFeatureFlagPayloads"] = "bootstrap_feature_flag_payloads";
8
10
  PostHogPersistedProperty["OverrideFeatureFlags"] = "override_feature_flags";
9
11
  PostHogPersistedProperty["Queue"] = "queue";
10
12
  PostHogPersistedProperty["OptedOut"] = "opted_out";
@@ -15,6 +17,7 @@ var PostHogPersistedProperty;
15
17
  PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
16
18
  PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
17
19
  PostHogPersistedProperty["SessionReplay"] = "session_replay";
20
+ PostHogPersistedProperty["DecideEndpointWasHit"] = "decide_endpoint_was_hit";
18
21
  })(PostHogPersistedProperty || (PostHogPersistedProperty = {}));
19
22
 
20
23
  function assert(truthyValue, message) {
@@ -58,6 +61,9 @@ function safeSetTimeout(fn, timeout) {
58
61
  // We unref if available to prevent Node.js hanging on exit
59
62
  t?.unref && t?.unref();
60
63
  return t;
64
+ }
65
+ function getFetch() {
66
+ return typeof fetch !== 'undefined' ? fetch : typeof global.fetch !== 'undefined' ? global.fetch : undefined;
61
67
  }
62
68
 
63
69
  // Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
@@ -1438,12 +1444,14 @@ class PostHogCore extends PostHogCoreStateless {
1438
1444
  .filter((flag) => !!bootstrapfeatureFlags[flag])
1439
1445
  .reduce((res, key) => ((res[key] = bootstrapfeatureFlags[key] || false), res), {});
1440
1446
  if (Object.keys(bootstrapFlags).length) {
1447
+ this.setPersistedProperty(PostHogPersistedProperty.BootstrapFeatureFlags, bootstrapFlags);
1441
1448
  const currentFlags = this.getPersistedProperty(PostHogPersistedProperty.FeatureFlags) || {};
1442
1449
  const newFeatureFlags = { ...bootstrapFlags, ...currentFlags };
1443
1450
  this.setKnownFeatureFlags(newFeatureFlags);
1444
1451
  }
1445
1452
  const bootstrapFlagPayloads = bootstrap.featureFlagPayloads;
1446
1453
  if (bootstrapFlagPayloads && Object.keys(bootstrapFlagPayloads).length) {
1454
+ this.setPersistedProperty(PostHogPersistedProperty.BootstrapFeatureFlagPayloads, bootstrapFlagPayloads);
1447
1455
  const currentFlagPayloads = this.getPersistedProperty(PostHogPersistedProperty.FeatureFlagPayloads) || {};
1448
1456
  const newFeatureFlagPayloads = { ...bootstrapFlagPayloads, ...currentFlagPayloads };
1449
1457
  this.setKnownFeatureFlagPayloads(newFeatureFlagPayloads);
@@ -1759,6 +1767,8 @@ class PostHogCore extends PostHogCoreStateless {
1759
1767
  }
1760
1768
  this.setKnownFeatureFlags(newFeatureFlags);
1761
1769
  this.setKnownFeatureFlagPayloads(Object.fromEntries(Object.entries(newFeatureFlagPayloads || {}).map(([k, v]) => [k, this._parsePayload(v)])));
1770
+ // Mark that we hit the /decide endpoint so we can capture this in the $feature_flag_called event
1771
+ this.setPersistedProperty(PostHogPersistedProperty.DecideEndpointWasHit, true);
1762
1772
  const sessionReplay = res?.sessionRecording;
1763
1773
  if (sessionReplay) {
1764
1774
  this.setPersistedProperty(PostHogPersistedProperty.SessionReplay, sessionReplay);
@@ -1805,6 +1815,10 @@ class PostHogCore extends PostHogCoreStateless {
1805
1815
  this.capture('$feature_flag_called', {
1806
1816
  $feature_flag: key,
1807
1817
  $feature_flag_response: response,
1818
+ $feature_flag_bootstrapped_response: this.getPersistedProperty(PostHogPersistedProperty.BootstrapFeatureFlags)?.[key],
1819
+ $feature_flag_bootstrapped_payload: this.getPersistedProperty(PostHogPersistedProperty.BootstrapFeatureFlagPayloads)?.[key],
1820
+ // If we haven't yet received a response from the /decide endpoint, we must have used the bootstrapped value
1821
+ $used_bootstrap_value: !this.getPersistedProperty(PostHogPersistedProperty.DecideEndpointWasHit),
1808
1822
  });
1809
1823
  }
1810
1824
  // If we have flags we either return the value (true or string) or false
@@ -1902,15 +1916,18 @@ class PostHogCore extends PostHogCoreStateless {
1902
1916
  }
1903
1917
  }
1904
1918
 
1905
- var version = "3.1.0";
1919
+ var version = "3.2.1";
1906
1920
 
1907
1921
  function getContext(window) {
1908
1922
  let context = {};
1909
- if (window.navigator) {
1923
+ if (window?.navigator) {
1910
1924
  const userAgent = window.navigator.userAgent;
1925
+ const osValue = os(window);
1911
1926
  context = {
1912
1927
  ...context,
1913
- $os: os(window),
1928
+ ...(osValue !== undefined && {
1929
+ $os: osValue
1930
+ }),
1914
1931
  $browser: browser(userAgent, window.navigator.vendor, !!window.opera),
1915
1932
  $referrer: window.document.referrer,
1916
1933
  $referring_domain: referringDomain(window.document.referrer),
@@ -2012,6 +2029,9 @@ function browserVersion(userAgent, vendor, opera) {
2012
2029
  return parseFloat(matches[matches.length - 2]);
2013
2030
  }
2014
2031
  function os(window) {
2032
+ if (!window?.navigator) {
2033
+ return undefined;
2034
+ }
2015
2035
  const a = window.navigator.userAgent;
2016
2036
  if (/Windows/i.test(a)) {
2017
2037
  if (/Phone/.test(a) || /WPDesktop/.test(a)) {
@@ -2031,7 +2051,7 @@ function os(window) {
2031
2051
  } else if (/CrOS/.test(a)) {
2032
2052
  return 'Chrome OS';
2033
2053
  } else {
2034
- return '';
2054
+ return undefined;
2035
2055
  }
2036
2056
  }
2037
2057
  function device(userAgent) {
@@ -2135,9 +2155,6 @@ const createStorageLike = store => {
2135
2155
  };
2136
2156
  };
2137
2157
  const checkStoreIsSupported = (storage, key = '__mplssupport__') => {
2138
- if (!window) {
2139
- return false;
2140
- }
2141
2158
  try {
2142
2159
  const val = 'xyz';
2143
2160
  storage.setItem(key, val);
@@ -2209,12 +2226,15 @@ class PostHog extends PostHogCore {
2209
2226
  super(apiKey, options);
2210
2227
  // posthog-js stores options in one object on
2211
2228
  this._storageKey = options?.persistence_name ? `ph_${options.persistence_name}` : `ph_${apiKey}_posthog`;
2212
- this._storage = getStorage(options?.persistence || 'localStorage', window);
2229
+ this._storage = getStorage(options?.persistence || 'localStorage', this.getWindow());
2213
2230
  this.setupBootstrap(options);
2214
2231
  if (options?.preloadFeatureFlags !== false) {
2215
2232
  this.reloadFeatureFlags();
2216
2233
  }
2217
2234
  }
2235
+ getWindow() {
2236
+ return typeof window !== 'undefined' ? window : undefined;
2237
+ }
2218
2238
  getPersistedProperty(key) {
2219
2239
  if (!this._storageCache) {
2220
2240
  this._storageCache = JSON.parse(this._storage.getItem(this._storageKey) || '{}') || {};
@@ -2233,7 +2253,12 @@ class PostHog extends PostHogCore {
2233
2253
  this._storage.setItem(this._storageKey, JSON.stringify(this._storageCache));
2234
2254
  }
2235
2255
  fetch(url, options) {
2236
- return window.fetch(url, options);
2256
+ const fetchFn = getFetch();
2257
+ if (!fetchFn) {
2258
+ // error will be handled by the caller (fetchWithRetry)
2259
+ return Promise.reject(new Error('Fetch API is not available in this environment.'));
2260
+ }
2261
+ return fetchFn(url, options);
2237
2262
  }
2238
2263
  getLibraryId() {
2239
2264
  return 'posthog-js-lite';
@@ -2247,7 +2272,7 @@ class PostHog extends PostHogCore {
2247
2272
  getCommonEventProperties() {
2248
2273
  return {
2249
2274
  ...super.getCommonEventProperties(),
2250
- ...getContext(window)
2275
+ ...getContext(this.getWindow())
2251
2276
  };
2252
2277
  }
2253
2278
  }