Enforce anon/pseudo-anon via types
parent
3135e42586
commit
74b0e52f9a
|
@ -1,11 +1,28 @@
|
|||
import posthog from 'posthog-js';
|
||||
import SdkConfig from './SdkConfig';
|
||||
|
||||
export interface IEvent {
|
||||
key: string;
|
||||
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.
|
||||
properties: {}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
export interface IOnboardingLoginBegin extends IEvent {
|
||||
key: "onboarding_login_begin",
|
||||
}
|
||||
|
@ -55,27 +72,32 @@ export class PosthogAnalytics {
|
|||
this.onlyTrackAnonymousEvents = enabled;
|
||||
}
|
||||
|
||||
public track<E extends IEvent>(
|
||||
key: E["key"],
|
||||
public trackPseudonymousEvent<E extends IPseudonymousEvent>(
|
||||
eventName: E["eventName"],
|
||||
properties: E["properties"],
|
||||
anonymous = false,
|
||||
) {
|
||||
if (!this.initialised) return;
|
||||
if (this.onlyTrackAnonymousEvents && !anonymous) return;
|
||||
|
||||
this.posthog.capture(key, properties);
|
||||
if (this.onlyTrackAnonymousEvents) return;
|
||||
this.posthog.capture(eventName, properties);
|
||||
}
|
||||
|
||||
public async trackRoomEvent<E extends IEvent>(
|
||||
key: E["key"],
|
||||
roomId: string,
|
||||
public trackAnonymousEvent<E extends IAnonymousEvent>(
|
||||
eventName: E["eventName"],
|
||||
properties: E["properties"],
|
||||
...args
|
||||
) {
|
||||
if (!this.initialised) return;
|
||||
this.posthog.capture(eventName, properties);
|
||||
}
|
||||
|
||||
public async trackRoomEvent<E extends IRoomEvent>(
|
||||
eventName: E["eventName"],
|
||||
roomId: string,
|
||||
properties: Omit<E["properties"], "roomId">,
|
||||
) {
|
||||
const updatedProperties = {
|
||||
...properties,
|
||||
hashedRoomId: roomId ? await hashHex(roomId) : null,
|
||||
};
|
||||
this.track(key, updatedProperties, ...args);
|
||||
this.trackPseudonymousEvent(eventName, updatedProperties);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IEvent, PosthogAnalytics } from '../src/PosthogAnalytics';
|
||||
import { IAnonymousEvent, IRoomEvent, PosthogAnalytics } from '../src/PosthogAnalytics';
|
||||
import SdkConfig from '../src/SdkConfig';
|
||||
const crypto = require('crypto');
|
||||
|
||||
|
@ -12,13 +12,20 @@ class FakePosthog {
|
|||
}
|
||||
}
|
||||
|
||||
export interface ITestEvent extends IEvent {
|
||||
export interface ITestEvent extends IAnonymousEvent {
|
||||
key: "jest_test_event",
|
||||
properties: {
|
||||
foo: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ITestRoomEvent extends IRoomEvent {
|
||||
key: "jest_test_room_event",
|
||||
properties: {
|
||||
foo: string
|
||||
}
|
||||
}
|
||||
|
||||
describe("PosthogAnalytics", () => {
|
||||
let analytics: PosthogAnalytics;
|
||||
let fakePosthog: FakePosthog;
|
||||
|
@ -61,7 +68,7 @@ describe("PosthogAnalytics", () => {
|
|||
|
||||
it("Should pass track() to posthog", () => {
|
||||
analytics.init(false);
|
||||
analytics.track<ITestEvent>("jest_test_event", {
|
||||
analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
|
||||
foo: "bar",
|
||||
});
|
||||
expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
|
||||
|
@ -71,7 +78,7 @@ describe("PosthogAnalytics", () => {
|
|||
it("Should pass trackRoomEvent to posthog", () => {
|
||||
analytics.init(false);
|
||||
const roomId = "42";
|
||||
return analytics.trackRoomEvent<ITestEvent>("jest_test_event", roomId, {
|
||||
return analytics.trackRoomEvent<IRoomEvent>("jest_test_event", roomId, {
|
||||
foo: "bar",
|
||||
}).then(() => {
|
||||
expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
|
||||
|
@ -82,11 +89,17 @@ describe("PosthogAnalytics", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("Should silently not send messages if not inititalised", () => {
|
||||
analytics.track<ITestEvent>("jest_test_event", {
|
||||
it("Should silently not track if not inititalised", () => {
|
||||
analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
|
||||
foo: "bar",
|
||||
});
|
||||
|
||||
expect(fakePosthog.capture.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it("Should not track non-anonymous messages if onlyTrackAnonymousEvents is true", () => {
|
||||
analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
|
||||
foo: "bar",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue