element-web/src/PosthogAnalytics.ts

113 lines
3.4 KiB
TypeScript
Raw Normal View History

2021-07-21 06:40:39 +00:00
import posthog from 'posthog-js';
import SdkConfig from './SdkConfig';
2021-07-21 07:23:42 +00:00
interface IEvent {
// The event name that will be used by PostHog.
// TODO: standard format (camel case? snake? UpperCase?)
eventName: string;
// The properties of the event that will be stored in PostHog.
2021-07-21 06:40:39 +00:00
properties: {}
}
2021-07-21 07:23:42 +00:00
// 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, hashed user IDs or room IDs.
export interface IPseudonymousEvent extends IEvent {}
// If an event extends IAnonymousEvent, the event strictly contains *only* anonymous data which
// may be sent without explicit user consent.
export interface IAnonymousEvent extends IEvent {}
export interface IRoomEvent extends IPseudonymousEvent {
hashedRoomId: string
}
2021-07-21 06:40:39 +00:00
export interface IOnboardingLoginBegin extends IEvent {
key: "onboarding_login_begin",
}
const hashHex = async (input: string): Promise<string> => {
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("");
};
export class PosthogAnalytics {
private onlyTrackAnonymousEvents = false;
private initialised = false;
private posthog = null;
private static _instance = null;
public static instance(): PosthogAnalytics {
if (!this.instance) {
this._instance = new PosthogAnalytics(posthog);
}
return this._instance;
}
constructor(posthog) {
this.posthog = posthog;
}
public init(onlyTrackAnonymousEvents: boolean) {
if (Boolean(navigator.doNotTrack === "1")) {
this.initialised = false;
return;
}
this.onlyTrackAnonymousEvents = onlyTrackAnonymousEvents;
const posthogConfig = SdkConfig.get()["posthog"];
if (posthogConfig) {
this.posthog.init(posthogConfig.projectApiKey, { api_host: posthogConfig.apiHost });
this.initialised = true;
}
}
2021-07-21 07:38:58 +00:00
public async identifyUser(userId: string) {
if (this.onlyTrackAnonymousEvents) return;
this.posthog.identify(await hashHex(userId));
}
2021-07-21 06:40:39 +00:00
public isInitialised(): boolean {
return this.initialised;
}
public setOnlyTrackAnonymousEvents(enabled: boolean) {
this.onlyTrackAnonymousEvents = enabled;
}
2021-07-21 07:23:42 +00:00
public trackPseudonymousEvent<E extends IPseudonymousEvent>(
eventName: E["eventName"],
2021-07-21 06:40:39 +00:00
properties: E["properties"],
) {
if (!this.initialised) return;
2021-07-21 07:23:42 +00:00
if (this.onlyTrackAnonymousEvents) return;
this.posthog.capture(eventName, properties);
}
2021-07-21 06:40:39 +00:00
2021-07-21 07:23:42 +00:00
public trackAnonymousEvent<E extends IAnonymousEvent>(
eventName: E["eventName"],
properties: E["properties"],
) {
if (!this.initialised) return;
this.posthog.capture(eventName, properties);
2021-07-21 06:40:39 +00:00
}
2021-07-21 07:23:42 +00:00
public async trackRoomEvent<E extends IRoomEvent>(
eventName: E["eventName"],
2021-07-21 06:40:39 +00:00
roomId: string,
2021-07-21 07:23:42 +00:00
properties: Omit<E["properties"], "roomId">,
2021-07-21 06:40:39 +00:00
) {
const updatedProperties = {
...properties,
hashedRoomId: roomId ? await hashHex(roomId) : null,
};
2021-07-21 07:23:42 +00:00
this.trackPseudonymousEvent(eventName, updatedProperties);
2021-07-21 06:40:39 +00:00
}
}
2021-07-21 07:42:29 +00:00
export default function getAnalytics() {
return PosthogAnalytics.instance();
}