Send layout analytics as WebLayout (#9482)

pull/28217/head
Michael Telatynski 2022-11-04 09:10:37 +00:00 committed by GitHub
parent a347525781
commit 28ecdc0cb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 125 additions and 14 deletions

View File

@ -56,7 +56,7 @@
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@matrix-org/analytics-events": "^0.2.0", "@matrix-org/analytics-events": "^0.3.0",
"@matrix-org/matrix-wysiwyg": "^0.3.2", "@matrix-org/matrix-wysiwyg": "^0.3.2",
"@matrix-org/react-sdk-module-api": "^0.0.3", "@matrix-org/react-sdk-module-api": "^0.0.3",
"@sentry/browser": "^6.11.0", "@sentry/browser": "^6.11.0",

View File

@ -25,6 +25,11 @@ import SdkConfig from './SdkConfig';
import { MatrixClientPeg } from "./MatrixClientPeg"; import { MatrixClientPeg } from "./MatrixClientPeg";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import { ScreenName } from "./PosthogTrackers"; import { ScreenName } from "./PosthogTrackers";
import { ActionPayload } from "./dispatcher/payloads";
import { Action } from "./dispatcher/actions";
import { SettingUpdatedPayload } from "./dispatcher/payloads/SettingUpdatedPayload";
import dis from "./dispatcher/dispatcher";
import { Layout } from "./settings/enums/Layout";
/* Posthog analytics tracking. /* Posthog analytics tracking.
* *
@ -153,8 +158,41 @@ export class PosthogAnalytics {
} else { } else {
this.enabled = false; this.enabled = false;
} }
dis.register(this.onAction);
SettingsStore.monitorSetting("layout", null);
SettingsStore.monitorSetting("useCompactLayout", null);
this.onLayoutUpdated();
} }
private onLayoutUpdated = () => {
let layout: UserProperties["WebLayout"];
switch (SettingsStore.getValue("layout")) {
case Layout.IRC:
layout = "IRC";
break;
case Layout.Bubble:
layout = "Bubble";
break;
case Layout.Group:
layout = SettingsStore.getValue("useCompactLayout") ? "Compact" : "Group";
break;
}
// This is known to clobber other devices but is a good enough solution
// to get an idea of how much use each layout gets.
this.setProperty("WebLayout", layout);
};
private onAction = (payload: ActionPayload) => {
if (payload.action !== Action.SettingUpdated) return;
const settingsPayload = payload as SettingUpdatedPayload;
if (["layout", "useCompactLayout"].includes(settingsPayload.settingName)) {
this.onLayoutUpdated();
}
};
// we persist the last `$screen_name` and send it for all events until it is replaced // we persist the last `$screen_name` and send it for all events until it is replaced
private lastScreen: ScreenName = "Loading"; private lastScreen: ScreenName = "Loading";
@ -192,7 +230,7 @@ export class PosthogAnalytics {
private static async getPlatformProperties(): Promise<PlatformProperties> { private static async getPlatformProperties(): Promise<PlatformProperties> {
const platform = PlatformPeg.get(); const platform = PlatformPeg.get();
let appVersion; let appVersion: string;
try { try {
appVersion = await platform.getAppVersion(); appVersion = await platform.getAppVersion();
} catch (e) { } catch (e) {

View File

@ -17,15 +17,14 @@ limitations under the License.
import { mocked } from 'jest-mock'; import { mocked } from 'jest-mock';
import { PostHog } from 'posthog-js'; import { PostHog } from 'posthog-js';
import { import { Anonymity, getRedactedCurrentLocation, IPosthogEvent, PosthogAnalytics } from '../src/PosthogAnalytics';
Anonymity,
getRedactedCurrentLocation,
IPosthogEvent,
PosthogAnalytics,
} from '../src/PosthogAnalytics';
import SdkConfig from '../src/SdkConfig'; import SdkConfig from '../src/SdkConfig';
import { getMockClientWithEventEmitter } from './test-utils'; import { getMockClientWithEventEmitter } from './test-utils';
import SettingsStore from "../src/settings/SettingsStore";
import { Layout } from "../src/settings/enums/Layout";
import defaultDispatcher from "../src/dispatcher/dispatcher";
import { Action } from "../src/dispatcher/actions";
import { SettingLevel } from "../src/settings/SettingLevel";
const getFakePosthog = (): PostHog => ({ const getFakePosthog = (): PostHog => ({
capture: jest.fn(), capture: jest.fn(),
@ -37,7 +36,7 @@ const getFakePosthog = (): PostHog => ({
export interface ITestEvent extends IPosthogEvent { export interface ITestEvent extends IPosthogEvent {
eventName: "JestTestEvents"; eventName: "JestTestEvents";
foo: string; foo?: string;
} }
describe("PosthogAnalytics", () => { describe("PosthogAnalytics", () => {
@ -180,4 +179,78 @@ describe("PosthogAnalytics", () => {
expect(mocked(fakePosthog).identify.mock.calls[0][0]).toBe("existing_analytics_id"); expect(mocked(fakePosthog).identify.mock.calls[0][0]).toBe("existing_analytics_id");
}); });
}); });
describe("WebLayout", () => {
let analytics: PosthogAnalytics;
beforeEach(() => {
SdkConfig.put({
brand: "Testing",
posthog: {
project_api_key: "foo",
api_host: "bar",
},
});
analytics = new PosthogAnalytics(fakePosthog);
analytics.setAnonymity(Anonymity.Pseudonymous);
});
it("should send layout IRC correctly", async () => {
await SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC);
defaultDispatcher.dispatch({
action: Action.SettingUpdated,
settingName: "layout",
}, true);
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
"WebLayout": "IRC",
});
});
it("should send layout Bubble correctly", async () => {
await SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
defaultDispatcher.dispatch({
action: Action.SettingUpdated,
settingName: "layout",
}, true);
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
"WebLayout": "Bubble",
});
});
it("should send layout Group correctly", async () => {
await SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Group);
defaultDispatcher.dispatch({
action: Action.SettingUpdated,
settingName: "layout",
}, true);
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
"WebLayout": "Group",
});
});
it("should send layout Compact correctly", async () => {
await SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Group);
await SettingsStore.setValue("useCompactLayout", null, SettingLevel.DEVICE, true);
defaultDispatcher.dispatch({
action: Action.SettingUpdated,
settingName: "useCompactLayout",
}, true);
analytics.trackEvent<ITestEvent>({
eventName: "JestTestEvents",
});
expect(mocked(fakePosthog).capture.mock.calls[0][1]["$set"]).toStrictEqual({
"WebLayout": "Compact",
});
});
});
}); });

View File

@ -1664,10 +1664,10 @@
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
"@matrix-org/analytics-events@^0.2.0": "@matrix-org/analytics-events@^0.3.0":
version "0.2.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.2.0.tgz#453925c939ecdd5ca6c797d293deb8cf0933f1b8" resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.3.0.tgz#a428f7e3f164ffadf38f35bc0f0f9a3e47369ce6"
integrity sha512-+0/Sydm4MNOcqd8iySJmojVPB74Axba4BXlwTsiKmL5fgYqdUkwmqkO39K7Pn8i+a+8pg11oNvBPkpWs3O5Qww== integrity sha512-f1WIMA8tjNB3V5g1C34yIpIJK47z6IJ4SLiY4j+J9Gw4X8C3TKGTAx563rMcMvW3Uk/PFqnIBXtkavHBXoYJ9A==
"@matrix-org/matrix-wysiwyg@^0.3.2": "@matrix-org/matrix-wysiwyg@^0.3.2":
version "0.3.2" version "0.3.2"