Track room list sorting algorithm changes (#32556)

* Update analytics package

* Add method for tracking event

* Track event on resort

* Add test

* Fix lint
This commit is contained in:
R Midhun Suresh
2026-02-18 15:36:22 +05:30
committed by GitHub
parent 177bc4dad4
commit cb220afc46
5 changed files with 58 additions and 12 deletions
+1 -1
View File
@@ -58,7 +58,7 @@
"@fontsource/fira-code": "^5",
"@fontsource/inter": "^5",
"@formatjs/intl-segmenter": "^12.0.0",
"@matrix-org/analytics-events": "^0.31.0",
"@matrix-org/analytics-events": "^0.32.0",
"@matrix-org/emojibase-bindings": "^1.5.0",
"@matrix-org/react-sdk-module-api": "^2.4.0",
"@sentry/browser": "^10.0.0",
+5 -5
View File
@@ -100,8 +100,8 @@ importers:
specifier: ^12.0.0
version: 12.1.1
'@matrix-org/analytics-events':
specifier: ^0.31.0
version: 0.31.0
specifier: ^0.32.0
version: 0.32.0
'@matrix-org/emojibase-bindings':
specifier: ^1.5.0
version: 1.5.0
@@ -2642,8 +2642,8 @@ packages:
'@maplibre/vt-pbf@4.2.1':
resolution: {integrity: sha512-IxZBGq/+9cqf2qdWlFuQ+ZfoMhWpxDUGQZ/poPHOJBvwMUT1GuxLo6HgYTou+xxtsOsjfbcjI8PZaPCtmt97rA==}
'@matrix-org/analytics-events@0.31.0':
resolution: {integrity: sha512-rZrtHt6X1cnleWPPSp56fngYBiq2Db1jQt+bATEUlDwwiMCrG3D5ojYqOQ03MlgySLIZLBAAam//bZAqiGWOwQ==}
'@matrix-org/analytics-events@0.32.0':
resolution: {integrity: sha512-Z5hl4wJdIvskFCOzHAh/7tQKlyvJ/5/JdvfTTySuJ/v47VmkCGvkdDD6ODT9+15psj3O8Cc2Ofgh2KqDJjd6kg==}
'@matrix-org/emojibase-bindings@1.5.0':
resolution: {integrity: sha512-+W9/ow2Z3iQa7ZOF698PBhwNcgGkn36B5Sr8VDPx8N8CH7+Uw+7TrtbtKPZVdgf4m/THmgmfX40jS5YDBsLaYg==}
@@ -12612,7 +12612,7 @@ snapshots:
pbf: 4.0.1
supercluster: 8.0.1
'@matrix-org/analytics-events@0.31.0': {}
'@matrix-org/analytics-events@0.32.0': {}
'@matrix-org/emojibase-bindings@1.5.0':
dependencies:
+24
View File
@@ -10,10 +10,12 @@ import { PureComponent, type SyntheticEvent } from "react";
import { type WebScreen as ScreenEvent } from "@matrix-org/analytics-events/types/typescript/WebScreen";
import { type Interaction as InteractionEvent } from "@matrix-org/analytics-events/types/typescript/Interaction";
import { type PinUnpinAction } from "@matrix-org/analytics-events/types/typescript/PinUnpinAction";
import { type RoomListSortingAlgorithmChanged } from "@matrix-org/analytics-events/types/typescript/RoomListSortingAlgorithmChanged";
import PageType from "./PageTypes";
import Views from "./Views";
import { PosthogAnalytics } from "./PosthogAnalytics";
import { SortingAlgorithm } from "./stores/room-list-v3/skip-list/sorters";
export type ScreenName = ScreenEvent["$current_url"];
export type InteractionName = InteractionEvent["name"];
@@ -38,6 +40,12 @@ const loggedInPageTypeMap: Record<PageType | string, ScreenName> = {
[PageType.UserView]: "User",
};
const SortingAlgorithmMap: Record<SortingAlgorithm, RoomListSortingAlgorithmChanged["newAlgorithm"]> = {
[SortingAlgorithm.Recency]: "Activity",
[SortingAlgorithm.Unread]: "Unread",
[SortingAlgorithm.Alphabetic]: "Alphabetic",
};
export default class PosthogTrackers {
private static internalInstance: PosthogTrackers;
@@ -112,6 +120,22 @@ export default class PosthogTrackers {
from,
});
}
/**
* Track when the user chooses a different sorting algorithm for the room-list.
* @param oldAlgorithm - The old algorithm.
* @param newAlgorithm - The new algorithm.
*/
public static trackRoomListSortingAlgorithmChange(
oldAlgorithm: SortingAlgorithm,
newAlgorithm: SortingAlgorithm,
): void {
PosthogAnalytics.instance.trackEvent<RoomListSortingAlgorithmChanged>({
eventName: "RoomListSortingAlgorithmChanged",
oldAlgorithm: SortingAlgorithmMap[oldAlgorithm],
newAlgorithm: SortingAlgorithmMap[newAlgorithm],
});
}
}
export class PosthogScreenTracker extends PureComponent<{ screenName: ScreenName }> {
@@ -170,20 +170,26 @@ export class RoomListHeaderViewModel
};
public sort = (option: SortOption): void => {
let sortingAlgorithm: SortingAlgorithm;
const oldSortingAlgorithm = RoomListStoreV3.instance.activeSortAlgorithm;
let newSortingAlgorithm: SortingAlgorithm;
switch (option) {
case "alphabetical":
sortingAlgorithm = SortingAlgorithm.Alphabetic;
newSortingAlgorithm = SortingAlgorithm.Alphabetic;
break;
case "recent":
sortingAlgorithm = SortingAlgorithm.Recency;
newSortingAlgorithm = SortingAlgorithm.Recency;
break;
case "unread-first":
sortingAlgorithm = SortingAlgorithm.Unread;
newSortingAlgorithm = SortingAlgorithm.Unread;
break;
}
RoomListStoreV3.instance.resort(sortingAlgorithm);
RoomListStoreV3.instance.resort(newSortingAlgorithm);
this.snapshot.merge({ activeSortOption: option });
// Record analytics for this action
if (oldSortingAlgorithm) {
PosthogTrackers.trackRoomListSortingAlgorithmChange(oldSortingAlgorithm, newSortingAlgorithm);
}
};
public toggleMessagePreview = (): void => {
@@ -25,6 +25,7 @@ import {
} from "../../../src/utils/space";
import { createTestClient, mkSpace } from "../../test-utils";
import { createRoom, hasCreateRoomRights } from "../../../src/viewmodels/room-list/utils";
import PosthogTrackers from "../../../src/PosthogTrackers";
jest.mock("../../../src/PosthogTrackers", () => ({
trackInteraction: jest.fn(),
@@ -276,10 +277,25 @@ describe("RoomListHeaderViewModel", () => {
const resortSpy = jest.spyOn(RoomListStoreV3.instance, "resort").mockImplementation(jest.fn());
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
vm.sort(option);
expect(resortSpy).toHaveBeenCalledWith(expectedAlgorithm);
});
it("should track analytics on resort", () => {
jest.spyOn(RoomListStoreV3.instance, "activeSortAlgorithm", "get").mockReturnValue(
SortingAlgorithm.Alphabetic,
);
PosthogTrackers.trackRoomListSortingAlgorithmChange = jest.fn();
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
jest.spyOn(RoomListStoreV3.instance, "resort").mockImplementation(jest.fn());
vm.sort("unread-first");
expect(PosthogTrackers.trackRoomListSortingAlgorithmChange).toHaveBeenCalledWith(
SortingAlgorithm.Alphabetic,
SortingAlgorithm.Unread,
);
});
it("should toggle message preview from enabled to disabled", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
if (settingName === "RoomList.showMessagePreview") return true;