posthog-js-lite 3.4.1 → 3.5.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/CHANGELOG.md +22 -0
- package/README.md +21 -2
- package/lib/index.cjs.js +720 -106
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +315 -22
- package/lib/index.esm.js +720 -106
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/featureFlagUtils.d.ts +34 -0
- package/lib/posthog-core/src/index.d.ts +43 -11
- package/lib/posthog-core/src/patch.d.ts +3 -0
- package/lib/posthog-core/src/types.d.ts +305 -15
- package/lib/posthog-core/src/utils.d.ts +4 -0
- package/lib/posthog-web/src/posthog-web.d.ts +3 -0
- package/lib/posthog-web/src/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/posthog-web.ts +52 -0
- package/src/types.ts +1 -0
- package/test/posthog-web.spec.ts +193 -2
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FeatureFlagDetail, FeatureFlagValue, PostHogDecideResponse, PostHogV3DecideResponse, PostHogV4DecideResponse, PartialWithRequired, PostHogFeatureFlagsResponse } from './types';
|
|
2
|
+
export declare const normalizeDecideResponse: (decideResponse: PartialWithRequired<PostHogV4DecideResponse, 'flags'> | PartialWithRequired<PostHogV3DecideResponse, 'featureFlags' | 'featureFlagPayloads'>) => PostHogFeatureFlagsResponse;
|
|
3
|
+
/**
|
|
4
|
+
* Get the flag values from the flags v4 response.
|
|
5
|
+
* @param flags - The flags
|
|
6
|
+
* @returns The flag values
|
|
7
|
+
*/
|
|
8
|
+
export declare const getFlagValuesFromFlags: (flags: PostHogDecideResponse['flags']) => PostHogDecideResponse['featureFlags'];
|
|
9
|
+
/**
|
|
10
|
+
* Get the payloads from the flags v4 response.
|
|
11
|
+
* @param flags - The flags
|
|
12
|
+
* @returns The payloads
|
|
13
|
+
*/
|
|
14
|
+
export declare const getPayloadsFromFlags: (flags: PostHogDecideResponse['flags']) => PostHogDecideResponse['featureFlagPayloads'];
|
|
15
|
+
/**
|
|
16
|
+
* Get the flag details from the legacy v3 flags and payloads. As such, it will lack the reason, id, version, and description.
|
|
17
|
+
* @param decideResponse - The decide response
|
|
18
|
+
* @returns The flag details
|
|
19
|
+
*/
|
|
20
|
+
export declare const getFlagDetailsFromFlagsAndPayloads: (decideResponse: PostHogFeatureFlagsResponse) => PostHogDecideResponse['flags'];
|
|
21
|
+
export declare const getFeatureFlagValue: (detail: FeatureFlagDetail | undefined) => FeatureFlagValue | undefined;
|
|
22
|
+
export declare const parsePayload: (response: any) => any;
|
|
23
|
+
/**
|
|
24
|
+
* Get the normalized flag details from the flags and payloads.
|
|
25
|
+
* This is used to convert things like boostrap and stored feature flags and payloads to the v4 format.
|
|
26
|
+
* This helps us ensure backwards compatibility.
|
|
27
|
+
* If a key exists in the featureFlagPayloads that is not in the featureFlags, we treat it as a true feature flag.
|
|
28
|
+
*
|
|
29
|
+
* @param featureFlags - The feature flags
|
|
30
|
+
* @param featureFlagPayloads - The feature flag payloads
|
|
31
|
+
* @returns The normalized flag details
|
|
32
|
+
*/
|
|
33
|
+
export declare const createDecideResponseFromFlagsAndPayloads: (featureFlags: PostHogV3DecideResponse['featureFlags'], featureFlagPayloads: PostHogV3DecideResponse['featureFlagPayloads']) => PostHogFeatureFlagsResponse;
|
|
34
|
+
export declare const updateFlagValue: (flag: FeatureFlagDetail, value: FeatureFlagValue) => FeatureFlagDetail;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import { PostHogFetchOptions, PostHogFetchResponse, PostHogAutocaptureElement, PostHogDecideResponse, PostHogCoreOptions, PostHogEventProperties, PostHogPersistedProperty, PostHogCaptureOptions, JsonType } from './types';
|
|
1
|
+
import { PostHogFetchOptions, PostHogFetchResponse, PostHogAutocaptureElement, PostHogDecideResponse, PostHogCoreOptions, PostHogEventProperties, PostHogPersistedProperty, PostHogCaptureOptions, JsonType, PostHogRemoteConfig, FeatureFlagValue, PostHogFeatureFlagDetails, FeatureFlagDetail, SurveyResponse } from './types';
|
|
2
2
|
import { RetriableOptions } from './utils';
|
|
3
|
-
export * as utils from './utils';
|
|
4
3
|
import { LZString } from './lz-string';
|
|
5
4
|
import { SimpleEventEmitter } from './eventemitter';
|
|
5
|
+
export * as utils from './utils';
|
|
6
6
|
export declare abstract class PostHogCoreStateless {
|
|
7
7
|
readonly apiKey: string;
|
|
8
8
|
readonly host: string;
|
|
9
9
|
readonly flushAt: number;
|
|
10
|
+
readonly preloadFeatureFlags: boolean;
|
|
11
|
+
readonly disableSurveys: boolean;
|
|
10
12
|
private maxBatchSize;
|
|
11
13
|
private maxQueueSize;
|
|
12
14
|
private flushInterval;
|
|
13
15
|
private flushPromise;
|
|
14
16
|
private requestTimeout;
|
|
15
17
|
private featureFlagsRequestTimeoutMs;
|
|
18
|
+
private remoteConfigRequestTimeoutMs;
|
|
16
19
|
private captureMode;
|
|
17
20
|
private removeDebugCallback?;
|
|
18
21
|
private disableGeoip;
|
|
@@ -25,6 +28,7 @@ export declare abstract class PostHogCoreStateless {
|
|
|
25
28
|
protected _retryOptions: RetriableOptions;
|
|
26
29
|
protected _initPromise: Promise<void>;
|
|
27
30
|
protected _isInitialized: boolean;
|
|
31
|
+
protected _remoteConfigResponsePromise?: Promise<PostHogRemoteConfig | undefined>;
|
|
28
32
|
abstract fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
|
|
29
33
|
abstract getLibraryId(): string;
|
|
30
34
|
abstract getLibraryVersion(): string;
|
|
@@ -58,19 +62,36 @@ export declare abstract class PostHogCoreStateless {
|
|
|
58
62
|
*** GROUPS
|
|
59
63
|
***/
|
|
60
64
|
protected groupIdentifyStateless(groupType: string, groupKey: string | number, groupProperties?: PostHogEventProperties, options?: PostHogCaptureOptions, distinctId?: string, eventProperties?: PostHogEventProperties): void;
|
|
65
|
+
protected getRemoteConfig(): Promise<PostHogRemoteConfig | undefined>;
|
|
61
66
|
/***
|
|
62
67
|
*** FEATURE FLAGS
|
|
63
68
|
***/
|
|
64
69
|
protected getDecide(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, extraPayload?: Record<string, any>): Promise<PostHogDecideResponse | undefined>;
|
|
65
|
-
protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<
|
|
70
|
+
protected getFeatureFlagStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<{
|
|
71
|
+
response: FeatureFlagValue | undefined;
|
|
72
|
+
requestId: string | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
protected getFeatureFlagDetailStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<{
|
|
75
|
+
response: FeatureFlagDetail | undefined;
|
|
76
|
+
requestId: string | undefined;
|
|
77
|
+
} | undefined>;
|
|
66
78
|
protected getFeatureFlagPayloadStateless(key: string, distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<JsonType | undefined>;
|
|
67
|
-
protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
|
|
68
|
-
protected
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
protected getFeatureFlagPayloadsStateless(distinctId: string, groups?: Record<string, string>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<PostHogDecideResponse['featureFlagPayloads'] | undefined>;
|
|
80
|
+
protected getFeatureFlagsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<{
|
|
81
|
+
flags: PostHogDecideResponse['featureFlags'] | undefined;
|
|
82
|
+
payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
|
|
83
|
+
requestId: PostHogDecideResponse['requestId'] | undefined;
|
|
84
|
+
}>;
|
|
85
|
+
protected getFeatureFlagsAndPayloadsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<{
|
|
71
86
|
flags: PostHogDecideResponse['featureFlags'] | undefined;
|
|
72
87
|
payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
|
|
88
|
+
requestId: PostHogDecideResponse['requestId'] | undefined;
|
|
73
89
|
}>;
|
|
90
|
+
protected getFeatureFlagDetailsStateless(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, disableGeoip?: boolean, flagKeysToEvaluate?: string[]): Promise<PostHogFeatureFlagDetails | undefined>;
|
|
91
|
+
/***
|
|
92
|
+
*** SURVEYS
|
|
93
|
+
***/
|
|
94
|
+
getSurveysStateless(): Promise<SurveyResponse['surveys']>;
|
|
74
95
|
/***
|
|
75
96
|
*** QUEUEING AND FLUSHING
|
|
76
97
|
***/
|
|
@@ -162,26 +183,37 @@ export declare abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
162
183
|
groupProperties(properties: {
|
|
163
184
|
[type: string]: Record<string, string>;
|
|
164
185
|
}): void;
|
|
186
|
+
private remoteConfigAsync;
|
|
165
187
|
/***
|
|
166
188
|
*** FEATURE FLAGS
|
|
167
189
|
***/
|
|
168
190
|
private decideAsync;
|
|
191
|
+
private cacheSessionReplay;
|
|
192
|
+
private _remoteConfigAsync;
|
|
169
193
|
private _decideAsync;
|
|
170
|
-
private
|
|
171
|
-
private
|
|
172
|
-
|
|
194
|
+
private setKnownFeatureFlagDetails;
|
|
195
|
+
private getKnownFeatureFlagDetails;
|
|
196
|
+
private getKnownFeatureFlags;
|
|
197
|
+
private getKnownFeatureFlagPayloads;
|
|
198
|
+
private getBootstrappedFeatureFlagDetails;
|
|
199
|
+
private setBootstrappedFeatureFlagDetails;
|
|
200
|
+
private getBootstrappedFeatureFlags;
|
|
201
|
+
private getBootstrappedFeatureFlagPayloads;
|
|
202
|
+
getFeatureFlag(key: string): FeatureFlagValue | undefined;
|
|
173
203
|
getFeatureFlagPayload(key: string): JsonType | undefined;
|
|
174
204
|
getFeatureFlagPayloads(): PostHogDecideResponse['featureFlagPayloads'] | undefined;
|
|
175
205
|
getFeatureFlags(): PostHogDecideResponse['featureFlags'] | undefined;
|
|
206
|
+
getFeatureFlagDetails(): PostHogFeatureFlagDetails | undefined;
|
|
176
207
|
getFeatureFlagsAndPayloads(): {
|
|
177
208
|
flags: PostHogDecideResponse['featureFlags'] | undefined;
|
|
178
209
|
payloads: PostHogDecideResponse['featureFlagPayloads'] | undefined;
|
|
179
210
|
};
|
|
180
211
|
isFeatureEnabled(key: string): boolean | undefined;
|
|
181
212
|
reloadFeatureFlags(cb?: (err?: Error, flags?: PostHogDecideResponse['featureFlags']) => void): void;
|
|
213
|
+
reloadRemoteConfigAsync(): Promise<PostHogRemoteConfig | undefined>;
|
|
182
214
|
reloadFeatureFlagsAsync(sendAnonDistinctId?: boolean): Promise<PostHogDecideResponse['featureFlags'] | undefined>;
|
|
183
215
|
onFeatureFlags(cb: (flags: PostHogDecideResponse['featureFlags']) => void): () => void;
|
|
184
|
-
onFeatureFlag(key: string, cb: (value:
|
|
216
|
+
onFeatureFlag(key: string, cb: (value: FeatureFlagValue) => void): () => void;
|
|
185
217
|
overrideFeatureFlag(flags: PostHogDecideResponse['featureFlags'] | null): Promise<void>;
|
|
186
218
|
/***
|
|
187
219
|
*** ERROR TRACKING
|
|
@@ -19,11 +19,23 @@ export type PostHogCoreOptions = {
|
|
|
19
19
|
sendFeatureFlagEvent?: boolean;
|
|
20
20
|
/** Whether to load feature flags when initialized or not */
|
|
21
21
|
preloadFeatureFlags?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether to load remote config when initialized or not
|
|
24
|
+
* Experimental support
|
|
25
|
+
* Default: false - Remote config is loaded by default
|
|
26
|
+
*/
|
|
27
|
+
disableRemoteConfig?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether to load surveys when initialized or not
|
|
30
|
+
* Experimental support
|
|
31
|
+
* Default: false - Surveys are loaded by default, but requires the `PostHogSurveyProvider` to be used
|
|
32
|
+
*/
|
|
33
|
+
disableSurveys?: boolean;
|
|
22
34
|
/** Option to bootstrap the library with given distinctId and feature flags */
|
|
23
35
|
bootstrap?: {
|
|
24
36
|
distinctId?: string;
|
|
25
37
|
isIdentifiedId?: boolean;
|
|
26
|
-
featureFlags?: Record<string,
|
|
38
|
+
featureFlags?: Record<string, FeatureFlagValue>;
|
|
27
39
|
featureFlagPayloads?: Record<string, JsonType>;
|
|
28
40
|
};
|
|
29
41
|
/** How many times we will retry HTTP requests. Defaults to 3. */
|
|
@@ -34,6 +46,8 @@ export type PostHogCoreOptions = {
|
|
|
34
46
|
requestTimeout?: number;
|
|
35
47
|
/** Timeout in milliseconds for feature flag calls. Defaults to 10 seconds for stateful clients, and 3 seconds for stateless. */
|
|
36
48
|
featureFlagsRequestTimeoutMs?: number;
|
|
49
|
+
/** Timeout in milliseconds for remote config calls. Defaults to 3 seconds. */
|
|
50
|
+
remoteConfigRequestTimeoutMs?: number;
|
|
37
51
|
/** For Session Analysis how long before we expire a session (defaults to 30 mins) */
|
|
38
52
|
sessionExpirationTimeSeconds?: number;
|
|
39
53
|
/** Whether to post events to PostHog in JSON or compressed format. Defaults to 'json' */
|
|
@@ -46,8 +60,10 @@ export declare enum PostHogPersistedProperty {
|
|
|
46
60
|
AnonymousId = "anonymous_id",
|
|
47
61
|
DistinctId = "distinct_id",
|
|
48
62
|
Props = "props",
|
|
63
|
+
FeatureFlagDetails = "feature_flag_details",
|
|
49
64
|
FeatureFlags = "feature_flags",
|
|
50
65
|
FeatureFlagPayloads = "feature_flag_payloads",
|
|
66
|
+
BootstrapFeatureFlagDetails = "bootstrap_feature_flag_details",
|
|
51
67
|
BootstrapFeatureFlags = "bootstrap_feature_flags",
|
|
52
68
|
BootstrapFeatureFlagPayloads = "bootstrap_feature_flag_payloads",
|
|
53
69
|
OverrideFeatureFlags = "override_feature_flags",
|
|
@@ -60,7 +76,11 @@ export declare enum PostHogPersistedProperty {
|
|
|
60
76
|
InstalledAppBuild = "installed_app_build",
|
|
61
77
|
InstalledAppVersion = "installed_app_version",
|
|
62
78
|
SessionReplay = "session_replay",
|
|
63
|
-
DecideEndpointWasHit = "decide_endpoint_was_hit"
|
|
79
|
+
DecideEndpointWasHit = "decide_endpoint_was_hit",
|
|
80
|
+
SurveyLastSeenDate = "survey_last_seen_date",
|
|
81
|
+
SurveysSeen = "surveys_seen",
|
|
82
|
+
Surveys = "surveys",
|
|
83
|
+
RemoteConfig = "remote_config"
|
|
64
84
|
}
|
|
65
85
|
export type PostHogFetchOptions = {
|
|
66
86
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH';
|
|
@@ -101,32 +121,302 @@ export type PostHogAutocaptureElement = {
|
|
|
101
121
|
} & {
|
|
102
122
|
[key: string]: any;
|
|
103
123
|
};
|
|
104
|
-
export type
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
};
|
|
108
|
-
editorParams: {
|
|
109
|
-
toolbarVersion: string;
|
|
110
|
-
jsURL: string;
|
|
124
|
+
export type PostHogRemoteConfig = {
|
|
125
|
+
sessionRecording?: boolean | {
|
|
126
|
+
[key: string]: JsonType;
|
|
111
127
|
};
|
|
112
|
-
|
|
113
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Whether surveys are enabled
|
|
130
|
+
*/
|
|
131
|
+
surveys?: boolean | Survey[];
|
|
132
|
+
/**
|
|
133
|
+
* Indicates if the team has any flags enabled (if not we don't need to load them)
|
|
134
|
+
*/
|
|
135
|
+
hasFeatureFlags?: boolean;
|
|
136
|
+
};
|
|
137
|
+
export type FeatureFlagValue = string | boolean;
|
|
138
|
+
export type PostHogDecideResponse = Omit<PostHogRemoteConfig, 'surveys' | 'hasFeatureFlags'> & {
|
|
114
139
|
featureFlags: {
|
|
115
|
-
[key: string]:
|
|
140
|
+
[key: string]: FeatureFlagValue;
|
|
116
141
|
};
|
|
117
142
|
featureFlagPayloads: {
|
|
118
143
|
[key: string]: JsonType;
|
|
119
144
|
};
|
|
145
|
+
flags: {
|
|
146
|
+
[key: string]: FeatureFlagDetail;
|
|
147
|
+
};
|
|
120
148
|
errorsWhileComputingFlags: boolean;
|
|
121
149
|
sessionRecording?: boolean | {
|
|
122
150
|
[key: string]: JsonType;
|
|
123
151
|
};
|
|
152
|
+
quotaLimited?: string[];
|
|
153
|
+
requestId?: string;
|
|
124
154
|
};
|
|
125
|
-
export type
|
|
126
|
-
|
|
127
|
-
|
|
155
|
+
export type PostHogFeatureFlagsResponse = PartialWithRequired<PostHogDecideResponse, 'flags' | 'featureFlags' | 'featureFlagPayloads' | 'requestId'>;
|
|
156
|
+
/**
|
|
157
|
+
* Creates a type with all properties of T, but makes only K properties required while the rest remain optional.
|
|
158
|
+
*
|
|
159
|
+
* @template T - The base type containing all properties
|
|
160
|
+
* @template K - Union type of keys from T that should be required
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* interface User {
|
|
164
|
+
* id: number;
|
|
165
|
+
* name: string;
|
|
166
|
+
* email?: string;
|
|
167
|
+
* age?: number;
|
|
168
|
+
* }
|
|
169
|
+
*
|
|
170
|
+
* // Makes 'id' and 'name' required, but 'email' and 'age' optional
|
|
171
|
+
* type RequiredUser = PartialWithRequired<User, 'id' | 'name'>;
|
|
172
|
+
*
|
|
173
|
+
* const user: RequiredUser = {
|
|
174
|
+
* id: 1, // Must be provided
|
|
175
|
+
* name: "John" // Must be provided
|
|
176
|
+
* // email and age are optional
|
|
177
|
+
* };
|
|
178
|
+
*/
|
|
179
|
+
export type PartialWithRequired<T, K extends keyof T> = {
|
|
180
|
+
[P in K]: T[P];
|
|
181
|
+
} & {
|
|
182
|
+
[P in Exclude<keyof T, K>]?: T[P];
|
|
128
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* These are the fields we care about from PostHogDecideResponse for feature flags.
|
|
186
|
+
*/
|
|
187
|
+
export type PostHogFeatureFlagDetails = PartialWithRequired<PostHogDecideResponse, 'flags' | 'featureFlags' | 'featureFlagPayloads' | 'requestId'>;
|
|
188
|
+
/**
|
|
189
|
+
* Models the response from the v3 `/decide` endpoint.
|
|
190
|
+
*/
|
|
191
|
+
export type PostHogV3DecideResponse = Omit<PostHogDecideResponse, 'flags'>;
|
|
192
|
+
export type PostHogV4DecideResponse = Omit<PostHogDecideResponse, 'featureFlags' | 'featureFlagPayloads'>;
|
|
193
|
+
/**
|
|
194
|
+
* The format of the flags object in persisted storage
|
|
195
|
+
*
|
|
196
|
+
* When we pull flags from persistence, we can normalize them to PostHogFeatureFlagDetails
|
|
197
|
+
* so that we can support v3 and v4 of the API.
|
|
198
|
+
*/
|
|
199
|
+
export type PostHogFlagsStorageFormat = Pick<PostHogFeatureFlagDetails, 'flags'>;
|
|
200
|
+
/**
|
|
201
|
+
* Models legacy flags and payloads return type for many public methods.
|
|
202
|
+
*/
|
|
203
|
+
export type PostHogFlagsAndPayloadsResponse = Partial<Pick<PostHogDecideResponse, 'featureFlags' | 'featureFlagPayloads'>>;
|
|
129
204
|
export type JsonType = string | number | boolean | null | {
|
|
130
205
|
[key: string]: JsonType;
|
|
131
206
|
} | Array<JsonType>;
|
|
132
207
|
export type FetchLike = (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>;
|
|
208
|
+
export type FeatureFlagDetail = {
|
|
209
|
+
key: string;
|
|
210
|
+
enabled: boolean;
|
|
211
|
+
variant: string | undefined;
|
|
212
|
+
reason: EvaluationReason | undefined;
|
|
213
|
+
metadata: FeatureFlagMetadata | undefined;
|
|
214
|
+
};
|
|
215
|
+
export type FeatureFlagMetadata = {
|
|
216
|
+
id: number | undefined;
|
|
217
|
+
version: number | undefined;
|
|
218
|
+
description: string | undefined;
|
|
219
|
+
payload: string | undefined;
|
|
220
|
+
};
|
|
221
|
+
export type EvaluationReason = {
|
|
222
|
+
code: string | undefined;
|
|
223
|
+
condition_index: number | undefined;
|
|
224
|
+
description: string | undefined;
|
|
225
|
+
};
|
|
226
|
+
export type SurveyAppearance = {
|
|
227
|
+
backgroundColor?: string;
|
|
228
|
+
submitButtonColor?: string;
|
|
229
|
+
submitButtonText?: string;
|
|
230
|
+
submitButtonTextColor?: string;
|
|
231
|
+
ratingButtonColor?: string;
|
|
232
|
+
ratingButtonActiveColor?: string;
|
|
233
|
+
autoDisappear?: boolean;
|
|
234
|
+
displayThankYouMessage?: boolean;
|
|
235
|
+
thankYouMessageHeader?: string;
|
|
236
|
+
thankYouMessageDescription?: string;
|
|
237
|
+
thankYouMessageDescriptionContentType?: SurveyQuestionDescriptionContentType;
|
|
238
|
+
thankYouMessageCloseButtonText?: string;
|
|
239
|
+
borderColor?: string;
|
|
240
|
+
position?: SurveyPosition;
|
|
241
|
+
placeholder?: string;
|
|
242
|
+
shuffleQuestions?: boolean;
|
|
243
|
+
surveyPopupDelaySeconds?: number;
|
|
244
|
+
widgetType?: SurveyWidgetType;
|
|
245
|
+
widgetSelector?: string;
|
|
246
|
+
widgetLabel?: string;
|
|
247
|
+
widgetColor?: string;
|
|
248
|
+
};
|
|
249
|
+
export declare enum SurveyPosition {
|
|
250
|
+
Left = "left",
|
|
251
|
+
Right = "right",
|
|
252
|
+
Center = "center"
|
|
253
|
+
}
|
|
254
|
+
export declare enum SurveyWidgetType {
|
|
255
|
+
Button = "button",
|
|
256
|
+
Tab = "tab",
|
|
257
|
+
Selector = "selector"
|
|
258
|
+
}
|
|
259
|
+
export declare enum SurveyType {
|
|
260
|
+
Popover = "popover",
|
|
261
|
+
API = "api",
|
|
262
|
+
Widget = "widget"
|
|
263
|
+
}
|
|
264
|
+
export type SurveyQuestion = BasicSurveyQuestion | LinkSurveyQuestion | RatingSurveyQuestion | MultipleSurveyQuestion;
|
|
265
|
+
export declare enum SurveyQuestionDescriptionContentType {
|
|
266
|
+
Html = "html",
|
|
267
|
+
Text = "text"
|
|
268
|
+
}
|
|
269
|
+
type SurveyQuestionBase = {
|
|
270
|
+
question: string;
|
|
271
|
+
id?: string;
|
|
272
|
+
description?: string;
|
|
273
|
+
descriptionContentType?: SurveyQuestionDescriptionContentType;
|
|
274
|
+
optional?: boolean;
|
|
275
|
+
buttonText?: string;
|
|
276
|
+
originalQuestionIndex: number;
|
|
277
|
+
branching?: NextQuestionBranching | EndBranching | ResponseBasedBranching | SpecificQuestionBranching;
|
|
278
|
+
};
|
|
279
|
+
export type BasicSurveyQuestion = SurveyQuestionBase & {
|
|
280
|
+
type: SurveyQuestionType.Open;
|
|
281
|
+
};
|
|
282
|
+
export type LinkSurveyQuestion = SurveyQuestionBase & {
|
|
283
|
+
type: SurveyQuestionType.Link;
|
|
284
|
+
link?: string;
|
|
285
|
+
};
|
|
286
|
+
export type RatingSurveyQuestion = SurveyQuestionBase & {
|
|
287
|
+
type: SurveyQuestionType.Rating;
|
|
288
|
+
display: SurveyRatingDisplay;
|
|
289
|
+
scale: 3 | 5 | 7 | 10;
|
|
290
|
+
lowerBoundLabel: string;
|
|
291
|
+
upperBoundLabel: string;
|
|
292
|
+
};
|
|
293
|
+
export declare enum SurveyRatingDisplay {
|
|
294
|
+
Number = "number",
|
|
295
|
+
Emoji = "emoji"
|
|
296
|
+
}
|
|
297
|
+
export type MultipleSurveyQuestion = SurveyQuestionBase & {
|
|
298
|
+
type: SurveyQuestionType.SingleChoice | SurveyQuestionType.MultipleChoice;
|
|
299
|
+
choices: string[];
|
|
300
|
+
hasOpenChoice?: boolean;
|
|
301
|
+
shuffleOptions?: boolean;
|
|
302
|
+
};
|
|
303
|
+
export declare enum SurveyQuestionType {
|
|
304
|
+
Open = "open",
|
|
305
|
+
MultipleChoice = "multiple_choice",
|
|
306
|
+
SingleChoice = "single_choice",
|
|
307
|
+
Rating = "rating",
|
|
308
|
+
Link = "link"
|
|
309
|
+
}
|
|
310
|
+
export declare enum SurveyQuestionBranchingType {
|
|
311
|
+
NextQuestion = "next_question",
|
|
312
|
+
End = "end",
|
|
313
|
+
ResponseBased = "response_based",
|
|
314
|
+
SpecificQuestion = "specific_question"
|
|
315
|
+
}
|
|
316
|
+
export type NextQuestionBranching = {
|
|
317
|
+
type: SurveyQuestionBranchingType.NextQuestion;
|
|
318
|
+
};
|
|
319
|
+
export type EndBranching = {
|
|
320
|
+
type: SurveyQuestionBranchingType.End;
|
|
321
|
+
};
|
|
322
|
+
export type ResponseBasedBranching = {
|
|
323
|
+
type: SurveyQuestionBranchingType.ResponseBased;
|
|
324
|
+
responseValues: Record<string, any>;
|
|
325
|
+
};
|
|
326
|
+
export type SpecificQuestionBranching = {
|
|
327
|
+
type: SurveyQuestionBranchingType.SpecificQuestion;
|
|
328
|
+
index: number;
|
|
329
|
+
};
|
|
330
|
+
export type SurveyResponse = {
|
|
331
|
+
surveys: Survey[];
|
|
332
|
+
};
|
|
333
|
+
export type SurveyCallback = (surveys: Survey[]) => void;
|
|
334
|
+
export declare enum SurveyMatchType {
|
|
335
|
+
Regex = "regex",
|
|
336
|
+
NotRegex = "not_regex",
|
|
337
|
+
Exact = "exact",
|
|
338
|
+
IsNot = "is_not",
|
|
339
|
+
Icontains = "icontains",
|
|
340
|
+
NotIcontains = "not_icontains"
|
|
341
|
+
}
|
|
342
|
+
export type SurveyElement = {
|
|
343
|
+
text?: string;
|
|
344
|
+
$el_text?: string;
|
|
345
|
+
tag_name?: string;
|
|
346
|
+
href?: string;
|
|
347
|
+
attr_id?: string;
|
|
348
|
+
attr_class?: string[];
|
|
349
|
+
nth_child?: number;
|
|
350
|
+
nth_of_type?: number;
|
|
351
|
+
attributes?: Record<string, any>;
|
|
352
|
+
event_id?: number;
|
|
353
|
+
order?: number;
|
|
354
|
+
group_id?: number;
|
|
355
|
+
};
|
|
356
|
+
export type SurveyRenderReason = {
|
|
357
|
+
visible: boolean;
|
|
358
|
+
disabledReason?: string;
|
|
359
|
+
};
|
|
360
|
+
export type Survey = {
|
|
361
|
+
id: string;
|
|
362
|
+
name: string;
|
|
363
|
+
description?: string;
|
|
364
|
+
type: SurveyType;
|
|
365
|
+
feature_flag_keys?: {
|
|
366
|
+
key: string;
|
|
367
|
+
value?: string;
|
|
368
|
+
}[];
|
|
369
|
+
linked_flag_key?: string;
|
|
370
|
+
targeting_flag_key?: string;
|
|
371
|
+
internal_targeting_flag_key?: string;
|
|
372
|
+
questions: SurveyQuestion[];
|
|
373
|
+
appearance?: SurveyAppearance;
|
|
374
|
+
conditions?: {
|
|
375
|
+
url?: string;
|
|
376
|
+
selector?: string;
|
|
377
|
+
seenSurveyWaitPeriodInDays?: number;
|
|
378
|
+
urlMatchType?: SurveyMatchType;
|
|
379
|
+
events?: {
|
|
380
|
+
repeatedActivation?: boolean;
|
|
381
|
+
values?: {
|
|
382
|
+
name: string;
|
|
383
|
+
}[];
|
|
384
|
+
};
|
|
385
|
+
actions?: {
|
|
386
|
+
values: SurveyActionType[];
|
|
387
|
+
};
|
|
388
|
+
deviceTypes?: string[];
|
|
389
|
+
deviceTypesMatchType?: SurveyMatchType;
|
|
390
|
+
};
|
|
391
|
+
start_date?: string;
|
|
392
|
+
end_date?: string;
|
|
393
|
+
current_iteration?: number;
|
|
394
|
+
current_iteration_start_date?: string;
|
|
395
|
+
};
|
|
396
|
+
export type SurveyActionType = {
|
|
397
|
+
id: number;
|
|
398
|
+
name?: string;
|
|
399
|
+
steps?: ActionStepType[];
|
|
400
|
+
};
|
|
401
|
+
/** Sync with plugin-server/src/types.ts */
|
|
402
|
+
export declare enum ActionStepStringMatching {
|
|
403
|
+
Contains = "contains",
|
|
404
|
+
Exact = "exact",
|
|
405
|
+
Regex = "regex"
|
|
406
|
+
}
|
|
407
|
+
export type ActionStepType = {
|
|
408
|
+
event?: string;
|
|
409
|
+
selector?: string;
|
|
410
|
+
/** @deprecated Only `selector` should be used now. */
|
|
411
|
+
tag_name?: string;
|
|
412
|
+
text?: string;
|
|
413
|
+
/** @default StringMatching.Exact */
|
|
414
|
+
text_matching?: ActionStepStringMatching;
|
|
415
|
+
href?: string;
|
|
416
|
+
/** @default ActionStepStringMatching.Exact */
|
|
417
|
+
href_matching?: ActionStepStringMatching;
|
|
418
|
+
url?: string;
|
|
419
|
+
/** @default StringMatching.Contains */
|
|
420
|
+
url_matching?: ActionStepStringMatching;
|
|
421
|
+
};
|
|
422
|
+
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { FetchLike } from './types';
|
|
2
|
+
export declare const NEW_FLAGS_ROLLOUT_PERCENTAGE = 1;
|
|
3
|
+
export declare const NEW_FLAGS_EXCLUDED_HASHES: Set<string>;
|
|
2
4
|
export declare function assert(truthyValue: any, message: string): void;
|
|
3
5
|
export declare function removeTrailingSlash(url: string): string;
|
|
4
6
|
export interface RetriableOptions {
|
|
@@ -13,3 +15,5 @@ export declare function safeSetTimeout(fn: () => void, timeout: number): any;
|
|
|
13
15
|
export declare const isPromise: (obj: any) => obj is Promise<any>;
|
|
14
16
|
export declare const isError: (x: unknown) => x is Error;
|
|
15
17
|
export declare function getFetch(): FetchLike | undefined;
|
|
18
|
+
export declare const isFunction: (f: any) => f is (...args: any[]) => any;
|
|
19
|
+
export declare function isTokenInRollout(token: string, percentage?: number, excludedHashes?: Set<string>): boolean;
|
|
@@ -4,6 +4,7 @@ export declare class PostHog extends PostHogCore {
|
|
|
4
4
|
private _storage;
|
|
5
5
|
private _storageCache;
|
|
6
6
|
private _storageKey;
|
|
7
|
+
private _lastPathname;
|
|
7
8
|
constructor(apiKey: string, options?: PostHogOptions);
|
|
8
9
|
private getWindow;
|
|
9
10
|
getPersistedProperty<T>(key: PostHogPersistedProperty): T | undefined;
|
|
@@ -13,4 +14,6 @@ export declare class PostHog extends PostHogCore {
|
|
|
13
14
|
getLibraryVersion(): string;
|
|
14
15
|
getCustomUserAgent(): void;
|
|
15
16
|
getCommonEventProperties(): any;
|
|
17
|
+
private setupHistoryEventTracking;
|
|
18
|
+
private captureNavigationEvent;
|
|
16
19
|
}
|
package/package.json
CHANGED
package/src/posthog-web.ts
CHANGED
|
@@ -9,11 +9,13 @@ import { PostHogStorage, getStorage } from './storage'
|
|
|
9
9
|
import { version } from '../package.json'
|
|
10
10
|
import { PostHogOptions } from './types'
|
|
11
11
|
import { getFetch } from 'posthog-core/src/utils'
|
|
12
|
+
import { patch } from '../../posthog-core/src/patch'
|
|
12
13
|
|
|
13
14
|
export class PostHog extends PostHogCore {
|
|
14
15
|
private _storage: PostHogStorage
|
|
15
16
|
private _storageCache: any
|
|
16
17
|
private _storageKey: string
|
|
18
|
+
private _lastPathname: string = ''
|
|
17
19
|
|
|
18
20
|
constructor(apiKey: string, options?: PostHogOptions) {
|
|
19
21
|
super(apiKey, options)
|
|
@@ -27,6 +29,11 @@ export class PostHog extends PostHogCore {
|
|
|
27
29
|
if (options?.preloadFeatureFlags !== false) {
|
|
28
30
|
this.reloadFeatureFlags()
|
|
29
31
|
}
|
|
32
|
+
|
|
33
|
+
if (options?.captureHistoryEvents && typeof window !== 'undefined') {
|
|
34
|
+
this._lastPathname = window?.location?.pathname || ''
|
|
35
|
+
this.setupHistoryEventTracking()
|
|
36
|
+
}
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
private getWindow(): Window | undefined {
|
|
@@ -84,4 +91,49 @@ export class PostHog extends PostHogCore {
|
|
|
84
91
|
...getContext(this.getWindow()),
|
|
85
92
|
}
|
|
86
93
|
}
|
|
94
|
+
|
|
95
|
+
private setupHistoryEventTracking(): void {
|
|
96
|
+
const window = this.getWindow()
|
|
97
|
+
if (!window) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Old fashioned, we could also use arrow functions but I think the closure for a patch is more reliable
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
103
|
+
const self = this
|
|
104
|
+
|
|
105
|
+
patch(window.history, 'pushState', (originalPushState) => {
|
|
106
|
+
return function patchedPushState(this: History, state: any, title: string, url?: string | URL | null): void {
|
|
107
|
+
;(originalPushState as History['pushState']).call(this, state, title, url)
|
|
108
|
+
self.captureNavigationEvent('pushState')
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
patch(window.history, 'replaceState', (originalReplaceState) => {
|
|
113
|
+
return function patchedReplaceState(this: History, state: any, title: string, url?: string | URL | null): void {
|
|
114
|
+
;(originalReplaceState as History['replaceState']).call(this, state, title, url)
|
|
115
|
+
self.captureNavigationEvent('replaceState')
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
// For popstate we need to listen to the event instead of overriding a method
|
|
120
|
+
window.addEventListener('popstate', () => {
|
|
121
|
+
this.captureNavigationEvent('popstate')
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private captureNavigationEvent(navigationType: 'pushState' | 'replaceState' | 'popstate'): void {
|
|
126
|
+
const window = this.getWindow()
|
|
127
|
+
if (!window) {
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const currentPathname = window.location.pathname
|
|
132
|
+
|
|
133
|
+
// Only capture pageview if the pathname has changed
|
|
134
|
+
if (currentPathname !== this._lastPathname) {
|
|
135
|
+
this.capture('$pageview', { navigation_type: navigationType })
|
|
136
|
+
this._lastPathname = currentPathname
|
|
137
|
+
}
|
|
138
|
+
}
|
|
87
139
|
}
|