diff --git a/package.json b/package.json
index b7e06fe012..9744aa7685 100644
--- a/package.json
+++ b/package.json
@@ -87,7 +87,6 @@
"pako": "^2.0.3",
"parse5": "^6.0.1",
"png-chunks-extract": "^1.0.0",
- "posthog-js": "1.12.1",
"prop-types": "^15.7.2",
"qrcode": "^1.4.4",
"re-resizable": "^6.9.0",
diff --git a/src/@types/posthog.d.ts b/src/@types/posthog.d.ts
deleted file mode 100644
index 1ca475cd3b..0000000000
--- a/src/@types/posthog.d.ts
+++ /dev/null
@@ -1,748 +0,0 @@
-// A clone of the type definitions from posthog-js, stripped of references to transitive
-// dependencies which we don't actually use, so that we don't need to install them.
-//
-// Original file lives in node_modules/posthog/dist/module.d.ts
-
-/* eslint-disable @typescript-eslint/member-delimiter-style */
-/* eslint-disable @typescript-eslint/naming-convention */
-/* eslint-disable camelcase */
-
-// Type definitions for exported methods
-
-declare class posthog {
- /**
- * This function initializes a new instance of the PostHog capturing object.
- * All new instances are added to the main posthog object as sub properties (such as
- * posthog.library_name) and also returned by this function. To define a
- * second instance on the page, you would call:
- *
- * posthog.init('new token', { your: 'config' }, 'library_name');
- *
- * and use it like so:
- *
- * posthog.library_name.capture(...);
- *
- * @param {String} token Your PostHog API token
- * @param {Object} [config] A dictionary of config options to override. See a list of default config options.
- * @param {String} [name] The name for the new posthog instance that you want created
- */
- static init(token: string, config?: posthog.Config, name?: string): posthog
-
- /**
- * Clears super properties and generates a new random distinct_id for this instance.
- * Useful for clearing data when a user logs out.
- */
- static reset(reset_device_id?: boolean): void
-
- /**
- * Capture an event. This is the most important and
- * frequently used PostHog function.
- *
- * ### Usage:
- *
- * // capture an event named 'Registered'
- * posthog.capture('Registered', {'Gender': 'Male', 'Age': 21});
- *
- * // capture an event using navigator.sendBeacon
- * posthog.capture('Left page', {'duration_seconds': 35}, {transport: 'sendBeacon'});
- *
- * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.
- * @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself.
- * @param {Object} [options] Optional configuration for this capture request.
- * @param {String} [options.transport] Transport method for network request ('XHR' or 'sendBeacon').
- */
- static capture(
- event_name: string,
- properties?: posthog.Properties,
- options?: { transport: 'XHR' | 'sendBeacon' }
- ): posthog.CaptureResult
-
- /**
- * Capture a page view event, which is currently ignored by the server.
- * This function is called by default on page load unless the
- * capture_pageview configuration variable is false.
- *
- * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
- * @api private
- */
- static capture_pageview(page?: string): void
-
- /**
- * Register a set of super properties, which are included with all
- * events. This will overwrite previous super property values.
- *
- * ### Usage:
- *
- * // register 'Gender' as a super property
- * posthog.register({'Gender': 'Female'});
- *
- * // register several super properties when a user signs up
- * posthog.register({
- * 'Email': 'jdoe@example.com',
- * 'Account Type': 'Free'
- * });
- *
- * @param {Object} properties An associative array of properties to store about the user
- * @param {Number} [days] How many days since the user's last visit to store the super properties
- */
- static register(properties: posthog.Properties, days?: number): void
-
- /**
- * Register a set of super properties only once. This will not
- * overwrite previous super property values, unlike register().
- *
- * ### Usage:
- *
- * // register a super property for the first time only
- * posthog.register_once({
- * 'First Login Date': new Date().toISOString()
- * });
- *
- * ### Notes:
- *
- * If default_value is specified, current super properties
- * with that value will be overwritten.
- *
- * @param {Object} properties An associative array of properties to store about the user
- * @param {*} [default_value] Value to override if already set in super properties (ex: 'False') Default: 'None'
- * @param {Number} [days] How many days since the users last visit to store the super properties
- */
- static register_once(properties: posthog.Properties, default_value?: posthog.Property, days?: number): void
-
- /**
- * Delete a super property stored with the current user.
- *
- * @param {String} property The name of the super property to remove
- */
- static unregister(property: string): void
-
- /**
- * Identify a user with a unique ID instead of a PostHog
- * randomly generated distinct_id. If the method is never called,
- * then unique visitors will be identified by a UUID generated
- * the first time they visit the site.
- *
- * If user properties are passed, they are also sent to posthog.
- *
- * ### Usage:
- *
- * posthog.identify('[user unique id]')
- * posthog.identify('[user unique id]', { email: 'john@example.com' })
- * posthog.identify('[user unique id]', {}, { referral_code: '12345' })
- *
- * ### Notes:
- *
- * You can call this function to overwrite a previously set
- * unique ID for the current user. PostHog cannot translate
- * between IDs at this time, so when you change a user's ID
- * they will appear to be a new user.
- *
- * When used alone, posthog.identify will change the user's
- * distinct_id to the unique ID provided. When used in tandem
- * with posthog.alias, it will allow you to identify based on
- * unique ID and map that back to the original, anonymous
- * distinct_id given to the user upon her first arrival to your
- * site (thus connecting anonymous pre-signup activity to
- * post-signup activity). Though the two work together, do not
- * call identify() at the same time as alias(). Calling the two
- * at the same time can cause a race condition, so it is best
- * practice to call identify on the original, anonymous ID
- * right after you've aliased it.
- *
- * @param {String} [unique_id] A string that uniquely identifies a user. If not provided, the distinct_id currently in the persistent store (cookie or localStorage) will be used.
- * @param {Object} [userProperties] Optional: An associative array of properties to store about the user
- * @param {Object} [userPropertiesToSetOnce] Optional: An associative array of properties to store about the user. If property is previously set, this does not override that value.
- */
- static identify(
- unique_id?: string,
- userPropertiesToSet?: posthog.Properties,
- userPropertiesToSetOnce?: posthog.Properties
- ): void
-
- /**
- * Create an alias, which PostHog will use to link two distinct_ids going forward (not retroactively).
- * Multiple aliases can map to the same original ID, but not vice-versa. Aliases can also be chained - the
- * following is a valid scenario:
- *
- * posthog.alias('new_id', 'existing_id');
- * ...
- * posthog.alias('newer_id', 'new_id');
- *
- * If the original ID is not passed in, we will use the current distinct_id - probably the auto-generated GUID.
- *
- * ### Notes:
- *
- * The best practice is to call alias() when a unique ID is first created for a user
- * (e.g., when a user first registers for an account and provides an email address).
- * alias() should never be called more than once for a given user, except to
- * chain a newer ID to a previously new ID, as described above.
- *
- * @param {String} alias A unique identifier that you want to use for this user in the future.
- * @param {String} [original] The current identifier being used for this user.
- */
- static alias(alias: string, original?: string): posthog.CaptureResult | number
-
- /**
- * Update the configuration of a posthog library instance.
- *
- * The default config is:
- *
- * {
- * // HTTP method for capturing requests
- * api_method: 'POST'
- *
- * // transport for sending requests ('XHR' or 'sendBeacon')
- * // NB: sendBeacon should only be used for scenarios such as
- * // page unload where a "best-effort" attempt to send is
- * // acceptable; the sendBeacon API does not support callbacks
- * // or any way to know the result of the request. PostHog
- * // capturing via sendBeacon will not support any event-
- * // batching or retry mechanisms.
- * api_transport: 'XHR'
- *
- * // Automatically capture clicks, form submissions and change events
- * autocapture: true
- *
- * // Capture rage clicks (beta) - useful for session recording
- * rageclick: false
- *
- * // super properties cookie expiration (in days)
- * cookie_expiration: 365
- *
- * // super properties span subdomains
- * cross_subdomain_cookie: true
- *
- * // debug mode
- * debug: false
- *
- * // if this is true, the posthog cookie or localStorage entry
- * // will be deleted, and no user persistence will take place
- * disable_persistence: false
- *
- * // if this is true, PostHog will automatically determine
- * // City, Region and Country data using the IP address of
- * //the client
- * ip: true
- *
- * // opt users out of capturing by this PostHog instance by default
- * opt_out_capturing_by_default: false
- *
- * // opt users out of browser data storage by this PostHog instance by default
- * opt_out_persistence_by_default: false
- *
- * // persistence mechanism used by opt-in/opt-out methods - cookie
- * // or localStorage - falls back to cookie if localStorage is unavailable
- * opt_out_capturing_persistence_type: 'localStorage'
- *
- * // customize the name of cookie/localStorage set by opt-in/opt-out methods
- * opt_out_capturing_cookie_prefix: null
- *
- * // type of persistent store for super properties (cookie/
- * // localStorage) if set to 'localStorage', any existing
- * // posthog cookie value with the same persistence_name
- * // will be transferred to localStorage and deleted
- * persistence: 'cookie'
- *
- * // name for super properties persistent store
- * persistence_name: ''
- *
- * // names of properties/superproperties which should never
- * // be sent with capture() calls
- * property_blacklist: []
- *
- * // if this is true, posthog cookies will be marked as
- * // secure, meaning they will only be transmitted over https
- * secure_cookie: false
- *
- * // should we capture a page view on page load
- * capture_pageview: true
- *
- * // if you set upgrade to be true, the library will check for
- * // a cookie from our old js library and import super
- * // properties from it, then the old cookie is deleted
- * // The upgrade config option only works in the initialization,
- * // so make sure you set it when you create the library.
- * upgrade: false
- *
- * // extra HTTP request headers to set for each API request, in
- * // the format {'Header-Name': value}
- * xhr_headers: {}
- *
- * // protocol for fetching in-app message resources, e.g.
- * // 'https://' or 'http://'; defaults to '//' (which defers to the
- * // current page's protocol)
- * inapp_protocol: '//'
- *
- * // whether to open in-app message link in new tab/window
- * inapp_link_new_window: false
- *
- * // a set of rrweb config options that PostHog users can configure
- * // see https://github.com/rrweb-io/rrweb/blob/master/guide.md
- * session_recording: {
- * blockClass: 'ph-no-capture',
- * blockSelector: null,
- * ignoreClass: 'ph-ignore-input',
- * maskAllInputs: false,
- * maskInputOptions: {},
- * maskInputFn: null,
- * slimDOMOptions: {},
- * collectFonts: false
- * }
- *
- * // prevent autocapture from capturing any attribute names on elements
- * mask_all_element_attributes: false
- *
- * // prevent autocapture from capturing textContent on all elements
- * mask_all_text: false
- *
- * // will disable requests to the /decide endpoint (please review documentation for details)
- * // autocapture, feature flags, compression and session recording will be disabled when set to `true`
- * advanced_disable_decide: false
- *
- * }
- *
- *
- * @param {Object} config A dictionary of new configuration values to update
- */
- static set_config(config: posthog.Config): void
-
- /**
- * returns the current config object for the library.
- */
- static get_config(prop_name: T): posthog.Config[T]
-
- /**
- * Returns the value of the super property named property_name. If no such
- * property is set, get_property() will return the undefined value.
- *
- * ### Notes:
- *
- * get_property() can only be called after the PostHog library has finished loading.
- * init() has a loaded function available to handle this automatically. For example:
- *
- * // grab value for 'user_id' after the posthog library has loaded
- * posthog.init('YOUR PROJECT TOKEN', {
- * loaded: function(posthog) {
- * user_id = posthog.get_property('user_id');
- * }
- * });
- *
- * @param {String} property_name The name of the super property you want to retrieve
- */
- static get_property(property_name: string): posthog.Property | undefined
-
- /**
- * Returns the current distinct id of the user. This is either the id automatically
- * generated by the library or the id that has been passed by a call to identify().
- *
- * ### Notes:
- *
- * get_distinct_id() can only be called after the PostHog library has finished loading.
- * init() has a loaded function available to handle this automatically. For example:
- *
- * // set distinct_id after the posthog library has loaded
- * posthog.init('YOUR PROJECT TOKEN', {
- * loaded: function(posthog) {
- * distinct_id = posthog.get_distinct_id();
- * }
- * });
- */
- static get_distinct_id(): string
-
- /**
- * Opt the user out of data capturing and cookies/localstorage for this PostHog instance
- *
- * ### Usage
- *
- * // opt user out
- * posthog.opt_out_capturing();
- *
- * // opt user out with different cookie configuration from PostHog instance
- * posthog.opt_out_capturing({
- * cookie_expiration: 30,
- * secure_cookie: true
- * });
- *
- * @param {Object} [options] A dictionary of config options to override
- * @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
- * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this PostHog instance's config)
- * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this PostHog instance's config)
- * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this PostHog instance's config)
- */
- static opt_out_capturing(options?: posthog.OptInOutCapturingOptions): void
-
- /**
- * Opt the user in to data capturing and cookies/localstorage for this PostHog instance
- *
- * ### Usage
- *
- * // opt user in
- * posthog.opt_in_capturing();
- *
- * // opt user in with specific event name, properties, cookie configuration
- * posthog.opt_in_capturing({
- * capture_event_name: 'User opted in',
- * capture_event_properties: {
- * 'Email': 'jdoe@example.com'
- * },
- * cookie_expiration: 30,
- * secure_cookie: true
- * });
- *
- * @param {Object} [options] A dictionary of config options to override
- * @param {function} [options.capture] Function used for capturing a PostHog event to record the opt-in action (default is this PostHog instance's capture method)
- * @param {string} [options.capture_event_name=$opt_in] Event name to be used for capturing the opt-in action
- * @param {Object} [options.capture_properties] Set of properties to be captured along with the opt-in action
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
- * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this PostHog instance's config)
- * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this PostHog instance's config)
- * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this PostHog instance's config)
- */
- static opt_in_capturing(options?: posthog.OptInOutCapturingOptions): void
-
- /**
- * Check whether the user has opted out of data capturing and cookies/localstorage for this PostHog instance
- *
- * ### Usage
- *
- * const has_opted_out = posthog.has_opted_out_capturing();
- * // use has_opted_out value
- *
- * @param {Object} [options] A dictionary of config options to override
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
- * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name
- * @returns {boolean} current opt-out status
- */
- static has_opted_out_capturing(options?: posthog.HasOptedInOutCapturingOptions): boolean
-
- /**
- * Check whether the user has opted in to data capturing and cookies/localstorage for this PostHog instance
- *
- * ### Usage
- *
- * const has_opted_in = posthog.has_opted_in_capturing();
- * // use has_opted_in value
- *
- * @param {Object} [options] A dictionary of config options to override
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
- * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name
- * @returns {boolean} current opt-in status
- */
- static has_opted_in_capturing(options?: posthog.HasOptedInOutCapturingOptions): boolean
-
- /**
- * Clear the user's opt in/out status of data capturing and cookies/localstorage for this PostHog instance
- *
- * ### Usage
- *
- * // clear user's opt-in/out status
- * posthog.clear_opt_in_out_capturing();
- *
- * // clear user's opt-in/out status with specific cookie configuration - should match
- * // configuration used when opt_in_capturing/opt_out_capturing methods were called.
- * posthog.clear_opt_in_out_capturing({
- * cookie_expiration: 30,
- * secure_cookie: true
- * });
- *
- * @param {Object} [options] A dictionary of config options to override
- * @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
- * @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
- * @param {string} [options.cookie_prefix=__ph_opt_in_out] Custom prefix to be used in the cookie/localstorage name
- * @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this PostHog instance's config)
- * @param {boolean} [options.cross_subdomain_cookie] Whether the opt-in cookie is set as cross-subdomain or not (overrides value specified in this PostHog instance's config)
- * @param {boolean} [options.secure_cookie] Whether the opt-in cookie is set as secure or not (overrides value specified in this PostHog instance's config)
- */
- static clear_opt_in_out_capturing(options?: posthog.ClearOptInOutCapturingOptions): void
-
- /*
- * See if feature flag is enabled for user.
- *
- * ### Usage:
- *
- * if(posthog.isFeatureEnabled('beta-feature')) { // do something }
- *
- * @param {Object|String} prop Key of the feature flag.
- * @param {Object|String} options (optional) If {send_event: false}, we won't send an $feature_flag_call event to PostHog.
- */
- static isFeatureEnabled(key: string, options?: posthog.isFeatureEnabledOptions): boolean
-
- /*
- * See if feature flags are available.
- *
- * ### Usage:
- *
- * posthog.onFeatureFlags(function(featureFlags) { // do something })
- *
- * @param {Function} [callback] The callback function will be called once the feature flags are ready. It'll return a list of feature flags enabled for the user.
- */
- static onFeatureFlags(callback: (flags: string[]) => void): false | undefined
-
- /*
- * Reload all feature flags for the user.
- *
- * ### Usage:
- *
- * posthog.reloadFeatureFlags()
- */
- static reloadFeatureFlags(): void
-
- static toString(): string
-
- /* Will log all capture requests to the Javascript console, including event properties for easy debugging */
- static debug(): void
-
- /*
- * Starts session recording and updates disable_session_recording to false.
- * Used for manual session recording management. By default, session recording is enabled and
- * starts automatically.
- *
- * ### Usage:
- *
- * posthog.startSessionRecording()
- */
- static startSessionRecording(): void
-
- /*
- * Stops session recording and updates disable_session_recording to true.
- *
- * ### Usage:
- *
- * posthog.stopSessionRecording()
- */
- static stopSessionRecording(): void
-
- /*
- * Check if session recording is currently running.
- *
- * ### Usage:
- *
- * const isSessionRecordingOn = posthog.sessionRecordingStarted()
- */
- static sessionRecordingStarted(): boolean
-}
-
-declare namespace posthog {
- /* eslint-disable @typescript-eslint/no-explicit-any */
- type Property = any;
- type Properties = Record;
- type CaptureResult = { event: string; properties: Properties } | undefined;
- type CaptureCallback = (response: any, data: any) => void;
- /* eslint-enable @typescript-eslint/no-explicit-any */
-
- interface Config {
- api_host?: string
- api_method?: string
- api_transport?: string
- autocapture?: boolean
- rageclick?: boolean
- cdn?: string
- cross_subdomain_cookie?: boolean
- persistence?: 'localStorage' | 'cookie' | 'memory'
- persistence_name?: string
- cookie_name?: string
- loaded?: (posthog_instance: typeof posthog) => void
- store_google?: boolean
- save_referrer?: boolean
- test?: boolean
- verbose?: boolean
- img?: boolean
- capture_pageview?: boolean
- debug?: boolean
- cookie_expiration?: number
- upgrade?: boolean
- disable_session_recording?: boolean
- disable_persistence?: boolean
- disable_cookie?: boolean
- secure_cookie?: boolean
- ip?: boolean
- opt_out_capturing_by_default?: boolean
- opt_out_persistence_by_default?: boolean
- opt_out_capturing_persistence_type?: 'localStorage' | 'cookie'
- opt_out_capturing_cookie_prefix?: string | null
- respect_dnt?: boolean
- property_blacklist?: string[]
- xhr_headers?: { [header_name: string]: string }
- inapp_protocol?: string
- inapp_link_new_window?: boolean
- request_batching?: boolean
- sanitize_properties?: (properties: posthog.Properties, event_name: string) => posthog.Properties
- properties_string_max_length?: number
- mask_all_element_attributes?: boolean
- mask_all_text?: boolean
- advanced_disable_decide?: boolean
- }
-
- interface OptInOutCapturingOptions {
- clear_persistence: boolean
- persistence_type: string
- cookie_prefix: string
- cookie_expiration: number
- cross_subdomain_cookie: boolean
- secure_cookie: boolean
- }
-
- interface HasOptedInOutCapturingOptions {
- persistence_type: string
- cookie_prefix: string
- }
-
- interface ClearOptInOutCapturingOptions {
- enable_persistence: boolean
- persistence_type: string
- cookie_prefix: string
- cookie_expiration: number
- cross_subdomain_cookie: boolean
- secure_cookie: boolean
- }
-
- interface isFeatureEnabledOptions {
- send_event: boolean
- }
-
- export class persistence {
- static properties(): posthog.Properties
-
- static load(): void
-
- static save(): void
-
- static remove(): void
-
- static clear(): void
-
- /**
- * @param {Object} props
- * @param {*=} default_value
- * @param {number=} days
- */
- static register_once(props: Properties, default_value?: Property, days?: number): boolean
-
- /**
- * @param {Object} props
- * @param {number=} days
- */
- static register(props: posthog.Properties, days?: number): boolean
-
- static unregister(prop: string): void
-
- static update_campaign_params(): void
-
- static update_search_keyword(referrer: string): void
-
- static update_referrer_info(referrer: string): void
-
- static get_referrer_info(): posthog.Properties
-
- static safe_merge(props: posthog.Properties): posthog.Properties
-
- static update_config(config: posthog.Config): void
-
- static set_disabled(disabled: boolean): void
-
- static set_cross_subdomain(cross_subdomain: boolean): void
-
- static get_cross_subdomain(): boolean
-
- static set_secure(secure: boolean): void
-
- static set_event_timer(event_name: string, timestamp: Date): void
-
- static remove_event_timer(event_name: string): Date | undefined
- }
-
- export class people {
- /*
- * Set properties on a user record.
- *
- * ### Usage:
- *
- * posthog.people.set('gender', 'm');
- *
- * // or set multiple properties at once
- * posthog.people.set({
- * 'Company': 'Acme',
- * 'Plan': 'Premium',
- * 'Upgrade date': new Date()
- * });
- * // properties can be strings, integers, dates, or lists
- *
- * @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values.
- * @param {*} [to] A value to set on the given property name
- * @param {Function} [callback] If provided, the callback will be called after capturing the event.
- */
- static set(
- prop: posthog.Properties | string,
- to?: posthog.Property,
- callback?: posthog.CaptureCallback
- ): posthog.Properties
-
- /*
- * Set properties on a user record, only if they do not yet exist.
- * This will not overwrite previous people property values, unlike
- * people.set().
- *
- * ### Usage:
- *
- * posthog.people.set_once('First Login Date', new Date());
- *
- * // or set multiple properties at once
- * posthog.people.set_once({
- * 'First Login Date': new Date(),
- * 'Starting Plan': 'Premium'
- * });
- *
- * // properties can be strings, integers or dates
- *
- * @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values.
- * @param {*} [to] A value to set on the given property name
- * @param {Function} [callback] If provided, the callback will be called after capturing the event.
- */
- static set_once(
- prop: posthog.Properties | string,
- to?: posthog.Property,
- callback?: posthog.CaptureCallback
- ): posthog.Properties
-
- static toString(): string
- }
-
- export class featureFlags {
- static getFlags(): string[]
-
- static reloadFeatureFlags(): void
-
- /*
- * See if feature flag is enabled for user.
- *
- * ### Usage:
- *
- * if(posthog.isFeatureEnabled('beta-feature')) { // do something }
- *
- * @param {Object|String} prop Key of the feature flag.
- * @param {Object|String} options (optional) If {send_event: false}, we won't send an $feature_flag_call event to PostHog.
- */
- static isFeatureEnabled(key: string, options?: { send_event?: boolean }): boolean
-
- /*
- * See if feature flags are available.
- *
- * ### Usage:
- *
- * posthog.onFeatureFlags(function(featureFlags) { // do something })
- *
- * @param {Function} [callback] The callback function will be called once the feature flags are ready. It'll return a list of feature flags enabled for the user.
- */
- static onFeatureFlags(callback: (flags: string[]) => void): false | undefined
- }
-
- export class feature_flags extends featureFlags {}
-}
-
-export type PostHog = typeof posthog;
-
-export default posthog;
diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts
index e48fd52cb1..410124a637 100644
--- a/src/Lifecycle.ts
+++ b/src/Lifecycle.ts
@@ -48,7 +48,6 @@ import { Jitsi } from "./widgets/Jitsi";
import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY } from "./BasePlatform";
import ThreepidInviteStore from "./stores/ThreepidInviteStore";
import CountlyAnalytics from "./CountlyAnalytics";
-import { PosthogAnalytics } from "./PosthogAnalytics";
import CallHandler from './CallHandler';
import LifecycleCustomisations from "./customisations/Lifecycle";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
@@ -574,8 +573,6 @@ async function doSetLoggedIn(
await abortLogin();
}
- PosthogAnalytics.instance.updateAnonymityFromSettings(credentials.userId);
-
Analytics.setLoggedIn(credentials.guest, credentials.homeserverUrl);
MatrixClientPeg.replaceUsingCreds(credentials);
@@ -703,8 +700,6 @@ export function logout(): void {
CountlyAnalytics.instance.enable(/* anonymous = */ true);
}
- PosthogAnalytics.instance.logout();
-
if (MatrixClientPeg.get().isGuest()) {
// logout doesn't work for guest sessions
// Also we sometimes want to re-log in a guest session if we abort the login.
diff --git a/src/PosthogAnalytics.ts b/src/PosthogAnalytics.ts
deleted file mode 100644
index 860a155aff..0000000000
--- a/src/PosthogAnalytics.ts
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
-Copyright 2021 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import posthog, { PostHog } from 'posthog-js';
-import PlatformPeg from './PlatformPeg';
-import SdkConfig from './SdkConfig';
-import SettingsStore from './settings/SettingsStore';
-
-/* Posthog analytics tracking.
- *
- * Anonymity behaviour is as follows:
- *
- * - If Posthog isn't configured in `config.json`, events are not sent.
- * - If [Do Not Track](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/doNotTrack) is
- * enabled, events are not sent (this detection is built into posthog and turned on via the
- * `respect_dnt` flag being passed to `posthog.init`).
- * - If the `feature_pseudonymous_analytics_opt_in` labs flag is `true`, track pseudonomously, i.e.
- * hash all matrix identifiers in tracking events (user IDs, room IDs etc) using SHA-256.
- * - Otherwise, if the existing `analyticsOptIn` flag is `true`, track anonymously, i.e.
- * redact all matrix identifiers in tracking events.
- * - If both flags are false or not set, events are not sent.
- */
-
-interface IEvent {
- // The event name that will be used by PostHog. Event names should use snake_case.
- eventName: string;
-
- // The properties of the event that will be stored in PostHog. This is just a placeholder,
- // extending interfaces must override this with a concrete definition to do type validation.
- properties: {};
-}
-
-export enum Anonymity {
- Disabled,
- Anonymous,
- Pseudonymous
-}
-
-// If an event extends IPseudonymousEvent, the event contains pseudonymous data
-// that won't be sent unless the user has explicitly consented to pseudonymous tracking.
-// For example, it might contain hashed user IDs or room IDs.
-// Such events will be automatically dropped if PosthogAnalytics.anonymity isn't set to Pseudonymous.
-export interface IPseudonymousEvent extends IEvent {}
-
-// If an event extends IAnonymousEvent, the event strictly contains *only* anonymous data;
-// i.e. no identifiers that can be associated with the user.
-export interface IAnonymousEvent extends IEvent {}
-
-export interface IRoomEvent extends IPseudonymousEvent {
- hashedRoomId: string;
-}
-
-interface IPageView extends IAnonymousEvent {
- eventName: "$pageview";
- properties: {
- durationMs?: number;
- screen?: string;
- };
-}
-
-const hashHex = async (input: string): Promise => {
- const buf = new TextEncoder().encode(input);
- const digestBuf = await window.crypto.subtle.digest("sha-256", buf);
- return [...new Uint8Array(digestBuf)].map((b: number) => b.toString(16).padStart(2, "0")).join("");
-};
-
-const whitelistedScreens = new Set([
- "register", "login", "forgot_password", "soft_logout", "new", "settings", "welcome", "home", "start", "directory",
- "start_sso", "start_cas", "groups", "complete_security", "post_registration", "room", "user", "group",
-]);
-
-export async function getRedactedCurrentLocation(
- origin: string,
- hash: string,
- pathname: string,
- anonymity: Anonymity,
-): Promise {
- // Redact PII from the current location.
- // If anonymous is true, redact entirely, if false, substitute it with a hash.
- // For known screens, assumes a URL structure of //might/be/pii
- if (origin.startsWith('file://')) {
- pathname = "//";
- }
-
- let hashStr;
- if (hash == "") {
- hashStr = "";
- } else {
- let [beforeFirstSlash, screen, ...parts] = hash.split("/");
-
- if (!whitelistedScreens.has(screen)) {
- screen = "";
- }
-
- for (let i = 0; i < parts.length; i++) {
- parts[i] = anonymity === Anonymity.Anonymous ? `` : await hashHex(parts[i]);
- }
-
- hashStr = `${beforeFirstSlash}/${screen}/${parts.join("/")}`;
- }
- return origin + pathname + hashStr;
-}
-
-interface PlatformProperties {
- appVersion: string;
- appPlatform: string;
-}
-
-export class PosthogAnalytics {
- /* Wrapper for Posthog analytics.
- * 3 modes of anonymity are supported, governed by this.anonymity
- * - Anonymity.Disabled means *no data* is passed to posthog
- * - Anonymity.Anonymous means all identifers will be redacted before being passed to posthog
- * - Anonymity.Pseudonymous means all identifiers will be hashed via SHA-256 before being passed
- * to Posthog
- *
- * To update anonymity, call updateAnonymityFromSettings() or you can set it directly via setAnonymity().
- *
- * To pass an event to Posthog:
- *
- * 1. Declare a type for the event, extending IAnonymousEvent, IPseudonymousEvent or IRoomEvent.
- * 2. Call the appropriate track*() method. Pseudonymous events will be dropped when anonymity is
- * Anonymous or Disabled; Anonymous events will be dropped when anonymity is Disabled.
- */
-
- private anonymity = Anonymity.Disabled;
- // set true during the constructor if posthog config is present, otherwise false
- private enabled = false;
- private static _instance = null;
- private platformSuperProperties = {};
-
- public static get instance(): PosthogAnalytics {
- if (!this._instance) {
- this._instance = new PosthogAnalytics(posthog);
- }
- return this._instance;
- }
-
- constructor(private readonly posthog: PostHog) {
- const posthogConfig = SdkConfig.get()["posthog"];
- if (posthogConfig) {
- this.posthog.init(posthogConfig.projectApiKey, {
- api_host: posthogConfig.apiHost,
- autocapture: false,
- mask_all_text: true,
- mask_all_element_attributes: true,
- // This only triggers on page load, which for our SPA isn't particularly useful.
- // Plus, the .capture call originating from somewhere in posthog makes it hard
- // to redact URLs, which requires async code.
- //
- // To raise this manually, just call .capture("$pageview") or posthog.capture_pageview.
- capture_pageview: false,
- sanitize_properties: this.sanitizeProperties,
- respect_dnt: true,
- });
- this.enabled = true;
- } else {
- this.enabled = false;
- }
- }
-
- private sanitizeProperties = (properties: posthog.Properties): posthog.Properties => {
- // Callback from posthog to sanitize properties before sending them to the server.
- //
- // Here we sanitize posthog's built in properties which leak PII e.g. url reporting.
- // See utils.js _.info.properties in posthog-js.
-
- // Replace the $current_url with a redacted version.
- // $redacted_current_url is injected by this class earlier in capture(), as its generation
- // is async and can't be done in this non-async callback.
- if (!properties['$redacted_current_url']) {
- console.log("$redacted_current_url not set in sanitizeProperties, will drop $current_url entirely");
- }
- properties['$current_url'] = properties['$redacted_current_url'];
- delete properties['$redacted_current_url'];
-
- if (this.anonymity == Anonymity.Anonymous) {
- // drop referrer information for anonymous users
- properties['$referrer'] = null;
- properties['$referring_domain'] = null;
- properties['$initial_referrer'] = null;
- properties['$initial_referring_domain'] = null;
-
- // drop device ID, which is a UUID persisted in local storage
- properties['$device_id'] = null;
- }
-
- return properties;
- };
-
- private static getAnonymityFromSettings(): Anonymity {
- // determine the current anonymity level based on current user settings
-
- // "Send anonymous usage data which helps us improve Element. This will use a cookie."
- const analyticsOptIn = SettingsStore.getValue("analyticsOptIn", null, true);
-
- // (proposed wording) "Send pseudonymous usage data which helps us improve Element. This will use a cookie."
- //
- // TODO: Currently, this is only a labs flag, for testing purposes.
- const pseudonumousOptIn = SettingsStore.getValue("feature_pseudonymous_analytics_opt_in", null, true);
-
- let anonymity;
- if (pseudonumousOptIn) {
- anonymity = Anonymity.Pseudonymous;
- } else if (analyticsOptIn) {
- anonymity = Anonymity.Anonymous;
- } else {
- anonymity = Anonymity.Disabled;
- }
-
- return anonymity;
- }
-
- private registerSuperProperties(properties: posthog.Properties) {
- if (this.enabled) {
- this.posthog.register(properties);
- }
- }
-
- private static async getPlatformProperties(): Promise {
- const platform = PlatformPeg.get();
- let appVersion;
- try {
- appVersion = await platform.getAppVersion();
- } catch (e) {
- // this happens if no version is set i.e. in dev
- appVersion = "unknown";
- }
-
- return {
- appVersion,
- appPlatform: platform.getHumanReadableName(),
- };
- }
-
- private async capture(eventName: string, properties: posthog.Properties) {
- if (!this.enabled) {
- return;
- }
- const { origin, hash, pathname } = window.location;
- properties['$redacted_current_url'] = await getRedactedCurrentLocation(
- origin, hash, pathname, this.anonymity);
- this.posthog.capture(eventName, properties);
- }
-
- public isEnabled(): boolean {
- return this.enabled;
- }
-
- public setAnonymity(anonymity: Anonymity): void {
- // Update this.anonymity.
- // This is public for testing purposes, typically you want to call updateAnonymityFromSettings
- // to ensure this value is in step with the user's settings.
- if (this.enabled && (anonymity == Anonymity.Disabled || anonymity == Anonymity.Anonymous)) {
- // when transitioning to Disabled or Anonymous ensure we clear out any prior state
- // set in posthog e.g. distinct ID
- this.posthog.reset();
- // Restore any previously set platform super properties
- this.registerSuperProperties(this.platformSuperProperties);
- }
- this.anonymity = anonymity;
- }
-
- public async identifyUser(userId: string): Promise {
- if (this.anonymity == Anonymity.Pseudonymous) {
- this.posthog.identify(await hashHex(userId));
- }
- }
-
- public getAnonymity(): Anonymity {
- return this.anonymity;
- }
-
- public logout(): void {
- if (this.enabled) {
- this.posthog.reset();
- }
- this.setAnonymity(Anonymity.Anonymous);
- }
-
- public async trackPseudonymousEvent(
- eventName: E["eventName"],
- properties: E["properties"] = {},
- ) {
- if (this.anonymity == Anonymity.Anonymous || this.anonymity == Anonymity.Disabled) return;
- await this.capture(eventName, properties);
- }
-
- public async trackAnonymousEvent(
- eventName: E["eventName"],
- properties: E["properties"] = {},
- ): Promise {
- if (this.anonymity == Anonymity.Disabled) return;
- await this.capture(eventName, properties);
- }
-
- public async trackRoomEvent(
- eventName: E["eventName"],
- roomId: string,
- properties: Omit,
- ): Promise {
- const updatedProperties = {
- ...properties,
- hashedRoomId: roomId ? await hashHex(roomId) : null,
- };
- await this.trackPseudonymousEvent(eventName, updatedProperties);
- }
-
- public async trackPageView(durationMs: number): Promise {
- const hash = window.location.hash;
-
- let screen = null;
- const split = hash.split("/");
- if (split.length >= 2) {
- screen = split[1];
- }
-
- await this.trackAnonymousEvent("$pageview", {
- durationMs,
- screen,
- });
- }
-
- public async updatePlatformSuperProperties(): Promise {
- // Update super properties in posthog with our platform (app version, platform).
- // These properties will be subsequently passed in every event.
- //
- // This only needs to be done once per page lifetime. Note that getPlatformProperties
- // is async and can involve a network request if we are running in a browser.
- this.platformSuperProperties = await PosthogAnalytics.getPlatformProperties();
- this.registerSuperProperties(this.platformSuperProperties);
- }
-
- public async updateAnonymityFromSettings(userId?: string): Promise {
- // Update this.anonymity based on the user's analytics opt-in settings
- // Identify the user (via hashed user ID) to posthog if anonymity is pseudonmyous
- this.setAnonymity(PosthogAnalytics.getAnonymityFromSettings());
- if (userId && this.getAnonymity() == Anonymity.Pseudonymous) {
- await this.identifyUser(userId);
- }
- }
-}
diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx
index 60c78b5f9e..8cfe35c4cf 100644
--- a/src/components/structures/MatrixChat.tsx
+++ b/src/components/structures/MatrixChat.tsx
@@ -107,7 +107,6 @@ import UIStore, { UI_EVENTS } from "../../stores/UIStore";
import SoftLogout from './auth/SoftLogout';
import { makeRoomPermalink } from "../../utils/permalinks/Permalinks";
import { copyPlaintext } from "../../utils/strings";
-import { PosthogAnalytics } from '../../PosthogAnalytics';
/** constants for MatrixChat.state.view */
export enum Views {
@@ -388,10 +387,6 @@ export default class MatrixChat extends React.PureComponent {
if (SettingsStore.getValue("analyticsOptIn")) {
Analytics.enable();
}
-
- PosthogAnalytics.instance.updateAnonymityFromSettings();
- PosthogAnalytics.instance.updatePlatformSuperProperties();
-
CountlyAnalytics.instance.enable(/* anonymous = */ true);
}
@@ -448,7 +443,6 @@ export default class MatrixChat extends React.PureComponent {
const durationMs = this.stopPageChangeTimer();
Analytics.trackPageChange(durationMs);
CountlyAnalytics.instance.trackPageChange(durationMs);
- PosthogAnalytics.instance.trackPageView(durationMs);
}
if (this.focusComposer) {
dis.fire(Action.FocusSendMessageComposer);
diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
index 25b0b86cb1..79d501e712 100644
--- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
+++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js
@@ -36,7 +36,6 @@ import { UIFeature } from "../../../../../settings/UIFeature";
import { isE2eAdvancedPanelPossible } from "../../E2eAdvancedPanel";
import CountlyAnalytics from "../../../../../CountlyAnalytics";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
-import { PosthogAnalytics } from "../../../../../PosthogAnalytics";
export class IgnoredUser extends React.Component {
static propTypes = {
@@ -107,7 +106,6 @@ export default class SecurityUserSettingsTab extends React.Component {
_updateAnalytics = (checked) => {
checked ? Analytics.enable() : Analytics.disable();
CountlyAnalytics.instance.enable(/* anonymous = */ !checked);
- PosthogAnalytics.instance.updateAnonymityFromSettings(MatrixClientPeg.get().getUserId());
};
_onExportE2eKeysClicked = () => {
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 87cd9afb5b..3ad8daa85c 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -813,7 +813,6 @@
"Show message previews for reactions in DMs": "Show message previews for reactions in DMs",
"Show message previews for reactions in all rooms": "Show message previews for reactions in all rooms",
"Offline encrypted messaging using dehydrated devices": "Offline encrypted messaging using dehydrated devices",
- "Send pseudonymous analytics data": "Send pseudonymous analytics data",
"Enable advanced debugging for the room list": "Enable advanced debugging for the room list",
"Show info about bridges in room settings": "Show info about bridges in room settings",
"New layout switcher (with message bubbles)": "New layout switcher (with message bubbles)",
diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx
index cfe2c097fc..c36e2b90bf 100644
--- a/src/settings/Settings.tsx
+++ b/src/settings/Settings.tsx
@@ -41,7 +41,6 @@ import { Layout } from "./Layout";
import ReducedMotionController from './controllers/ReducedMotionController';
import IncompatibleController from "./controllers/IncompatibleController";
import SdkConfig from "../SdkConfig";
-import PseudonymousAnalyticsController from './controllers/PseudonymousAnalyticsController';
import NewLayoutSwitcherController from './controllers/NewLayoutSwitcherController';
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
@@ -269,13 +268,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
supportedLevels: LEVELS_FEATURE,
default: false,
},
- "feature_pseudonymous_analytics_opt_in": {
- isFeature: true,
- supportedLevels: LEVELS_FEATURE,
- displayName: _td('Send pseudonymous analytics data'),
- default: false,
- controller: new PseudonymousAnalyticsController(),
- },
"advancedRoomListLogging": {
// TODO: Remove flag before launch: https://github.com/vector-im/element-web/issues/14231
displayName: _td("Enable advanced debugging for the room list"),
diff --git a/src/settings/controllers/PseudonymousAnalyticsController.ts b/src/settings/controllers/PseudonymousAnalyticsController.ts
deleted file mode 100644
index a82b9685ef..0000000000
--- a/src/settings/controllers/PseudonymousAnalyticsController.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Copyright 2021 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import SettingController from "./SettingController";
-import { SettingLevel } from "../SettingLevel";
-import { PosthogAnalytics } from "../../PosthogAnalytics";
-import { MatrixClientPeg } from "../../MatrixClientPeg";
-
-export default class PseudonymousAnalyticsController extends SettingController {
- public onChange(level: SettingLevel, roomId: string, newValue: any) {
- PosthogAnalytics.instance.updateAnonymityFromSettings(MatrixClientPeg.get().getUserId());
- }
-}
diff --git a/test/PosthogAnalytics-test.ts b/test/PosthogAnalytics-test.ts
deleted file mode 100644
index 6cb1743051..0000000000
--- a/test/PosthogAnalytics-test.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
-Copyright 2021 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-import {
- Anonymity,
- getRedactedCurrentLocation,
- IAnonymousEvent,
- IPseudonymousEvent,
- IRoomEvent,
- PosthogAnalytics,
-} from '../src/PosthogAnalytics';
-
-import SdkConfig from '../src/SdkConfig';
-
-class FakePosthog {
- public capture;
- public init;
- public identify;
- public reset;
- public register;
-
- constructor() {
- this.capture = jest.fn();
- this.init = jest.fn();
- this.identify = jest.fn();
- this.reset = jest.fn();
- this.register = jest.fn();
- }
-}
-
-export interface ITestEvent extends IAnonymousEvent {
- key: "jest_test_event";
- properties: {
- foo: string;
- };
-}
-
-export interface ITestPseudonymousEvent extends IPseudonymousEvent {
- key: "jest_test_pseudo_event";
- properties: {
- foo: string;
- };
-}
-
-export interface ITestRoomEvent extends IRoomEvent {
- key: "jest_test_room_event";
- properties: {
- foo: string;
- };
-}
-
-describe("PosthogAnalytics", () => {
- let fakePosthog: FakePosthog;
- const shaHashes = {
- "42": "73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049",
- "some": "a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b",
- "pii": "bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4",
- "foo": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- };
-
- beforeEach(() => {
- fakePosthog = new FakePosthog();
-
- window.crypto = {
- subtle: {
- digest: async (_, encodedMessage) => {
- const message = new TextDecoder().decode(encodedMessage);
- const hexHash = shaHashes[message];
- const bytes = [];
- for (let c = 0; c < hexHash.length; c += 2) {
- bytes.push(parseInt(hexHash.substr(c, 2), 16));
- }
- return bytes;
- },
- },
- };
- });
-
- afterEach(() => {
- window.crypto = null;
- });
-
- describe("Initialisation", () => {
- it("Should not be enabled without config being set", () => {
- jest.spyOn(SdkConfig, "get").mockReturnValue({});
- const analytics = new PosthogAnalytics(fakePosthog);
- expect(analytics.isEnabled()).toBe(false);
- });
-
- it("Should be enabled if config is set", () => {
- jest.spyOn(SdkConfig, "get").mockReturnValue({
- posthog: {
- projectApiKey: "foo",
- apiHost: "bar",
- },
- });
- const analytics = new PosthogAnalytics(fakePosthog);
- analytics.setAnonymity(Anonymity.Pseudonymous);
- expect(analytics.isEnabled()).toBe(true);
- });
- });
-
- describe("Tracking", () => {
- let analytics: PosthogAnalytics;
-
- beforeEach(() => {
- jest.spyOn(SdkConfig, "get").mockReturnValue({
- posthog: {
- projectApiKey: "foo",
- apiHost: "bar",
- },
- });
-
- analytics = new PosthogAnalytics(fakePosthog);
- });
-
- it("Should pass trackAnonymousEvent() to posthog", async () => {
- analytics.setAnonymity(Anonymity.Pseudonymous);
- await analytics.trackAnonymousEvent("jest_test_event", {
- foo: "bar",
- });
- expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
- expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar");
- });
-
- it("Should pass trackRoomEvent to posthog", async () => {
- analytics.setAnonymity(Anonymity.Pseudonymous);
- const roomId = "42";
- await analytics.trackRoomEvent("jest_test_event", roomId, {
- foo: "bar",
- });
- expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
- expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar");
- expect(fakePosthog.capture.mock.calls[0][1]["hashedRoomId"])
- .toEqual("73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049");
- });
-
- it("Should pass trackPseudonymousEvent() to posthog", async () => {
- analytics.setAnonymity(Anonymity.Pseudonymous);
- await analytics.trackPseudonymousEvent("jest_test_pseudo_event", {
- foo: "bar",
- });
- expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_pseudo_event");
- expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar");
- });
-
- it("Should not track pseudonymous messages if anonymous", async () => {
- analytics.setAnonymity(Anonymity.Anonymous);
- await analytics.trackPseudonymousEvent("jest_test_event", {
- foo: "bar",
- });
- expect(fakePosthog.capture.mock.calls.length).toBe(0);
- });
-
- it("Should not track any events if disabled", async () => {
- analytics.setAnonymity(Anonymity.Disabled);
- await analytics.trackPseudonymousEvent("jest_test_event", {
- foo: "bar",
- });
- await analytics.trackAnonymousEvent("jest_test_event", {
- foo: "bar",
- });
- await analytics.trackRoomEvent("room id", "foo", {
- foo: "bar",
- });
- await analytics.trackPageView(200);
- expect(fakePosthog.capture.mock.calls.length).toBe(0);
- });
-
- it("Should pseudonymise a location of a known screen", async () => {
- const location = await getRedactedCurrentLocation(
- "https://foo.bar", "#/register/some/pii", "/", Anonymity.Pseudonymous);
- expect(location).toBe(
- `https://foo.bar/#/register/\
-a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b/\
-bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
- });
-
- it("Should anonymise a location of a known screen", async () => {
- const location = await getRedactedCurrentLocation(
- "https://foo.bar", "#/register/some/pii", "/", Anonymity.Anonymous);
- expect(location).toBe("https://foo.bar/#/register//");
- });
-
- it("Should pseudonymise a location of an unknown screen", async () => {
- const location = await getRedactedCurrentLocation(
- "https://foo.bar", "#/not_a_screen_name/some/pii", "/", Anonymity.Pseudonymous);
- expect(location).toBe(
- `https://foo.bar/#//\
-a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b/\
-bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
- });
-
- it("Should anonymise a location of an unknown screen", async () => {
- const location = await getRedactedCurrentLocation(
- "https://foo.bar", "#/not_a_screen_name/some/pii", "/", Anonymity.Anonymous);
- expect(location).toBe("https://foo.bar/#///");
- });
-
- it("Should handle an empty hash", async () => {
- const location = await getRedactedCurrentLocation(
- "https://foo.bar", "", "/", Anonymity.Anonymous);
- expect(location).toBe("https://foo.bar/");
- });
-
- it("Should identify the user to posthog if pseudonymous", async () => {
- analytics.setAnonymity(Anonymity.Pseudonymous);
- await analytics.identifyUser("foo");
- expect(fakePosthog.identify.mock.calls[0][0])
- .toBe("2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae");
- });
-
- it("Should not identify the user to posthog if anonymous", async () => {
- analytics.setAnonymity(Anonymity.Anonymous);
- await analytics.identifyUser("foo");
- expect(fakePosthog.identify.mock.calls.length).toBe(0);
- });
- });
-});
diff --git a/tsconfig.json b/tsconfig.json
index b982d40b07..b139e8e8d1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -22,15 +22,10 @@
"es2019",
"dom",
"dom.iterable"
- ],
- "paths": {
- "posthog-js": [
- "./src/@types/posthog.d.ts"
- ]
- }
+ ]
},
"include": [
"./src/**/*.ts",
"./src/**/*.tsx"
- ],
+ ]
}
diff --git a/yarn.lock b/yarn.lock
index daed6f4377..2a03f640ee 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3601,11 +3601,6 @@ fbjs@^0.8.4:
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
-fflate@^0.4.1:
- version "0.4.8"
- resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
- integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
-
file-entry-cache@^6.0.0, file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@@ -6254,13 +6249,6 @@ postcss@^8.0.2:
nanoid "^3.1.23"
source-map-js "^0.6.2"
-posthog-js@1.12.1:
- version "1.12.1"
- resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.12.1.tgz#97834ee2574f34ffb5db2f5b07452c847e3c4d27"
- integrity sha512-Y3lzcWkS8xFY6Ryj3I4ees7qWP2WGkLw0Arcbk5xaT0+5YlA6UC2jlL/+fN9bz/Bl62EoN3BML901Cuot/QNjg==
- dependencies:
- fflate "^0.4.1"
-
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"