Enable analytics only while authenticated
The one place where we should log out of PostHog and reset our analytics ID is when the user is logging out. This matches the behavior in Element Web and makes sense, I think, because logging out is essentially a request for the app to forget who you are. This means we should also start analytics at the point of logging in / reauthenticating. I noticed while making this change that there was an unused branch in setClient, so I cleaned it up rather than making myself update it.
This commit is contained in:
@@ -50,7 +50,7 @@ export type ValidClientState = {
|
|||||||
reactions: boolean;
|
reactions: boolean;
|
||||||
thumbnails: boolean;
|
thumbnails: boolean;
|
||||||
};
|
};
|
||||||
setClient: (params?: SetClientParams) => void;
|
setClient: (client: MatrixClient, session: Session) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AuthenticatedClient = {
|
export type AuthenticatedClient = {
|
||||||
@@ -65,11 +65,6 @@ export type ErrorState = {
|
|||||||
error: Error;
|
error: Error;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SetClientParams = {
|
|
||||||
client: MatrixClient;
|
|
||||||
session: Session;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ClientContext = createContext<ClientState | undefined>(undefined);
|
const ClientContext = createContext<ClientState | undefined>(undefined);
|
||||||
|
|
||||||
export const ClientContextProvider = ClientContext.Provider;
|
export const ClientContextProvider = ClientContext.Provider;
|
||||||
@@ -79,7 +74,7 @@ export const useClientState = (): ClientState | undefined =>
|
|||||||
|
|
||||||
export function useClient(): {
|
export function useClient(): {
|
||||||
client?: MatrixClient;
|
client?: MatrixClient;
|
||||||
setClient?: (params?: SetClientParams) => void;
|
setClient?: (client: MatrixClient, session: Session) => void;
|
||||||
} {
|
} {
|
||||||
let client;
|
let client;
|
||||||
let setClient;
|
let setClient;
|
||||||
@@ -96,7 +91,7 @@ export function useClient(): {
|
|||||||
// Plain representation of the `ClientContext` as a helper for old components that expected an object with multiple fields.
|
// Plain representation of the `ClientContext` as a helper for old components that expected an object with multiple fields.
|
||||||
export function useClientLegacy(): {
|
export function useClientLegacy(): {
|
||||||
client?: MatrixClient;
|
client?: MatrixClient;
|
||||||
setClient?: (params?: SetClientParams) => void;
|
setClient?: (client: MatrixClient, session: Session) => void;
|
||||||
passwordlessUser: boolean;
|
passwordlessUser: boolean;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
@@ -160,7 +155,11 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
initializing.current = true;
|
initializing.current = true;
|
||||||
|
|
||||||
loadClient()
|
loadClient()
|
||||||
.then(setInitClientState)
|
.then((initResult) => {
|
||||||
|
setInitClientState(initResult);
|
||||||
|
if (PosthogAnalytics.instance.isEnabled())
|
||||||
|
PosthogAnalytics.instance.startListeningToSettingsChanges();
|
||||||
|
})
|
||||||
.catch((err) => logger.error(err))
|
.catch((err) => logger.error(err))
|
||||||
.finally(() => (initializing.current = false));
|
.finally(() => (initializing.current = false));
|
||||||
}, []);
|
}, []);
|
||||||
@@ -196,24 +195,20 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const setClient = useCallback(
|
const setClient = useCallback(
|
||||||
(clientParams?: SetClientParams) => {
|
(client: MatrixClient, session: Session) => {
|
||||||
const oldClient = initClientState?.client;
|
const oldClient = initClientState?.client;
|
||||||
const newClient = clientParams?.client;
|
if (oldClient && oldClient !== client) {
|
||||||
if (oldClient && oldClient !== newClient) {
|
|
||||||
oldClient.stopClient();
|
oldClient.stopClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientParams) {
|
saveSession(session);
|
||||||
saveSession(clientParams.session);
|
setInitClientState({
|
||||||
setInitClientState({
|
widgetApi: null,
|
||||||
widgetApi: null,
|
client,
|
||||||
client: clientParams.client,
|
passwordlessUser: session.passwordlessUser,
|
||||||
passwordlessUser: clientParams.session.passwordlessUser,
|
});
|
||||||
});
|
if (PosthogAnalytics.instance.isEnabled())
|
||||||
} else {
|
PosthogAnalytics.instance.startListeningToSettingsChanges();
|
||||||
clearSession();
|
|
||||||
setInitClientState(null);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[initClientState?.client],
|
[initClientState?.client],
|
||||||
);
|
);
|
||||||
@@ -229,6 +224,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
clearSession();
|
clearSession();
|
||||||
setInitClientState(null);
|
setInitClientState(null);
|
||||||
await navigate("/");
|
await navigate("/");
|
||||||
|
PosthogAnalytics.instance.logout();
|
||||||
PosthogAnalytics.instance.setRegistrationType(RegistrationType.Guest);
|
PosthogAnalytics.instance.setRegistrationType(RegistrationType.Guest);
|
||||||
}, [navigate, initClientState?.client]);
|
}, [navigate, initClientState?.client]);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import posthog, {
|
|||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
import { Buffer } from "buffer";
|
import { Buffer } from "buffer";
|
||||||
|
import { type Subscription } from "rxjs";
|
||||||
|
|
||||||
import { widget } from "../widget";
|
import { widget } from "../widget";
|
||||||
import {
|
import {
|
||||||
@@ -101,6 +102,7 @@ export class PosthogAnalytics {
|
|||||||
private anonymity = Anonymity.Disabled;
|
private anonymity = Anonymity.Disabled;
|
||||||
private platformSuperProperties = {};
|
private platformSuperProperties = {};
|
||||||
private registrationType: RegistrationType = RegistrationType.Guest;
|
private registrationType: RegistrationType = RegistrationType.Guest;
|
||||||
|
private optInListener: Subscription | null = null;
|
||||||
|
|
||||||
public static hasInstance(): boolean {
|
public static hasInstance(): boolean {
|
||||||
return Boolean(this.internalInstance);
|
return Boolean(this.internalInstance);
|
||||||
@@ -146,7 +148,6 @@ export class PosthogAnalytics {
|
|||||||
);
|
);
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
}
|
}
|
||||||
this.startListeningToSettingsChanges(); // Triggers maybeIdentifyUser
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private sanitizeProperties = (
|
private sanitizeProperties = (
|
||||||
@@ -328,6 +329,8 @@ export class PosthogAnalytics {
|
|||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
this.posthog.reset();
|
this.posthog.reset();
|
||||||
}
|
}
|
||||||
|
this.optInListener?.unsubscribe();
|
||||||
|
this.optInListener = null;
|
||||||
this.setAnonymity(Anonymity.Disabled);
|
this.setAnonymity(Anonymity.Disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +409,7 @@ export class PosthogAnalytics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private startListeningToSettingsChanges(): void {
|
public startListeningToSettingsChanges(): void {
|
||||||
// Listen to account data changes from sync so we can observe changes to relevant flags and update.
|
// Listen to account data changes from sync so we can observe changes to relevant flags and update.
|
||||||
// This is called -
|
// This is called -
|
||||||
// * On page load, when the account data is first received by sync
|
// * On page load, when the account data is first received by sync
|
||||||
@@ -415,7 +418,7 @@ export class PosthogAnalytics {
|
|||||||
// * When the user changes their preferences on this device
|
// * When the user changes their preferences on this device
|
||||||
// Note that for new accounts, pseudonymousAnalyticsOptIn won't be set, so updateAnonymityFromSettings
|
// Note that for new accounts, pseudonymousAnalyticsOptIn won't be set, so updateAnonymityFromSettings
|
||||||
// won't be called (i.e. this.anonymity will be left as the default, until the setting changes)
|
// won't be called (i.e. this.anonymity will be left as the default, until the setting changes)
|
||||||
optInAnalytics.value$.subscribe((optIn) => {
|
this.optInListener ??= optInAnalytics.value$.subscribe((optIn) => {
|
||||||
this.setAnonymity(optIn ? Anonymity.Pseudonymous : Anonymity.Disabled);
|
this.setAnonymity(optIn ? Anonymity.Pseudonymous : Anonymity.Disabled);
|
||||||
this.maybeIdentifyUser().catch(() =>
|
this.maybeIdentifyUser().catch(() =>
|
||||||
logger.log("Could not identify user"),
|
logger.log("Could not identify user"),
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const LoginPage: FC = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setClient({ client, session });
|
setClient(client, session);
|
||||||
|
|
||||||
const locationState = location.state;
|
const locationState = location.state;
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export const RegisterPage: FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setClient?.({ client: newClient, session });
|
setClient?.(newClient, session);
|
||||||
PosthogAnalytics.instance.eventSignup.cacheSignupEnd(new Date());
|
PosthogAnalytics.instance.eventSignup.cacheSignupEnd(new Date());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function useRegisterPasswordlessUser(): UseRegisterPasswordlessUserType {
|
|||||||
recaptchaResponse,
|
recaptchaResponse,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
setClient({ client, session });
|
setClient(client, session);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reset();
|
reset();
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export const UnauthenticatedView: FC = () => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (error.errcode === "M_ROOM_IN_USE") {
|
if (error.errcode === "M_ROOM_IN_USE") {
|
||||||
setOnFinished(() => {
|
setOnFinished(() => {
|
||||||
setClient({ client, session });
|
setClient(client, session);
|
||||||
const aliasLocalpart = roomAliasLocalpartFromRoomName(roomName);
|
const aliasLocalpart = roomAliasLocalpartFromRoomName(roomName);
|
||||||
navigate(`/${aliasLocalpart}`)?.catch((error) => {
|
navigate(`/${aliasLocalpart}`)?.catch((error) => {
|
||||||
logger.error("Failed to navigate to alias localpart", error);
|
logger.error("Failed to navigate to alias localpart", error);
|
||||||
@@ -111,7 +111,7 @@ export const UnauthenticatedView: FC = () => {
|
|||||||
if (!createRoomResult.password)
|
if (!createRoomResult.password)
|
||||||
throw new Error("Failed to create room with shared secret");
|
throw new Error("Failed to create room with shared secret");
|
||||||
|
|
||||||
setClient({ client, session });
|
setClient(client, session);
|
||||||
await navigate(
|
await navigate(
|
||||||
getRelativeRoomUrl(
|
getRelativeRoomUrl(
|
||||||
createRoomResult.roomId,
|
createRoomResult.roomId,
|
||||||
|
|||||||
Reference in New Issue
Block a user