Add way to track posthog user properties and send numSpaces (#7716)
							parent
							
								
									c01d46d7ff
								
							
						
					
					
						commit
						91ccbe4395
					
				|  | @ -90,7 +90,7 @@ | |||
|     "linkifyjs": "^4.0.0-beta.4", | ||||
|     "lodash": "^4.17.20", | ||||
|     "maplibre-gl": "^1.15.2", | ||||
|     "matrix-analytics-events": "github:matrix-org/matrix-analytics-events.git#dfa6feaa12bcfc8e99b05a148e12fff7f9d62f08", | ||||
|     "matrix-analytics-events": "github:matrix-org/matrix-analytics-events.git#53844e3f6f9fefa88384a996b2bf5e60bb301b94", | ||||
|     "matrix-events-sdk": "^0.0.1-beta.6", | ||||
|     "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", | ||||
|     "matrix-widget-api": "^0.1.0-beta.18", | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ limitations under the License. | |||
| import posthog, { PostHog } from 'posthog-js'; | ||||
| import { MatrixClient } from "matrix-js-sdk/src/client"; | ||||
| import { logger } from "matrix-js-sdk/src/logger"; | ||||
| import { UserProperties } from "matrix-analytics-events/types/typescript/UserProperties"; | ||||
| 
 | ||||
| import PlatformPeg from './PlatformPeg'; | ||||
| import SdkConfig from './SdkConfig'; | ||||
|  | @ -42,6 +43,10 @@ import SettingsStore from "./settings/SettingsStore"; | |||
| interface IEvent { | ||||
|     // The event name that will be used by PostHog. Event names should use camelCase.
 | ||||
|     eventName: string; | ||||
| 
 | ||||
|     // do not allow these to be sent manually, we enqueue them all for caching purposes
 | ||||
|     "$set"?: void; | ||||
|     "$set_once"?: void; | ||||
| } | ||||
| 
 | ||||
| export enum Anonymity { | ||||
|  | @ -109,6 +114,8 @@ export class PosthogAnalytics { | |||
|     private static _instance = null; | ||||
|     private platformSuperProperties = {}; | ||||
|     private static ANALYTICS_EVENT_TYPE = "im.vector.analytics"; | ||||
|     private propertiesForNextEvent: Partial<Record<"$set" | "$set_once", UserProperties>> = {}; | ||||
|     private userPropertyCache: UserProperties = {}; | ||||
| 
 | ||||
|     public static get instance(): PosthogAnalytics { | ||||
|         if (!this._instance) { | ||||
|  | @ -198,7 +205,11 @@ export class PosthogAnalytics { | |||
|         } | ||||
|         const { origin, hash, pathname } = window.location; | ||||
|         properties['$redacted_current_url'] = getRedactedCurrentLocation(origin, hash, pathname); | ||||
|         this.posthog.capture(eventName, properties); | ||||
|         this.posthog.capture(eventName, { | ||||
|             ...this.propertiesForNextEvent, | ||||
|             ...properties, | ||||
|         }); | ||||
|         this.propertiesForNextEvent = {}; | ||||
|     } | ||||
| 
 | ||||
|     public isEnabled(): boolean { | ||||
|  | @ -260,13 +271,29 @@ export class PosthogAnalytics { | |||
|         this.setAnonymity(Anonymity.Disabled); | ||||
|     } | ||||
| 
 | ||||
|     public trackEvent<E extends IEvent>( | ||||
|         event: E, | ||||
|     ): void { | ||||
|     public trackEvent<E extends IEvent>({ eventName, ...properties }: E): void { | ||||
|         if (this.anonymity == Anonymity.Disabled || this.anonymity == Anonymity.Anonymous) return; | ||||
|         const eventWithoutName = { ...event }; | ||||
|         delete eventWithoutName.eventName; | ||||
|         this.capture(event.eventName, eventWithoutName); | ||||
|         this.capture(eventName, properties); | ||||
|     } | ||||
| 
 | ||||
|     public setProperty<K extends keyof UserProperties>(key: K, value: UserProperties[K]): void { | ||||
|         if (this.userPropertyCache[key] === value) return; // nothing to do
 | ||||
|         this.userPropertyCache[key] = value; | ||||
| 
 | ||||
|         if (!this.propertiesForNextEvent["$set"]) { | ||||
|             this.propertiesForNextEvent["$set"] = {}; | ||||
|         } | ||||
|         this.propertiesForNextEvent["$set"][key] = value; | ||||
|     } | ||||
| 
 | ||||
|     public setPropertyOnce<K extends keyof UserProperties>(key: K, value: UserProperties[K]): void { | ||||
|         if (this.userPropertyCache[key]) return; // nothing to do
 | ||||
|         this.userPropertyCache[key] = value; | ||||
| 
 | ||||
|         if (!this.propertiesForNextEvent["$set_once"]) { | ||||
|             this.propertiesForNextEvent["$set_once"] = {}; | ||||
|         } | ||||
|         this.propertiesForNextEvent["$set_once"][key] = value; | ||||
|     } | ||||
| 
 | ||||
|     public async updatePlatformSuperProperties(): Promise<void> { | ||||
|  |  | |||
|  | @ -22,8 +22,6 @@ import { IRoomTimelineData } from "matrix-js-sdk/src/models/event-timeline-set"; | |||
| import dis from "../dispatcher/dispatcher"; | ||||
| import { ActionPayload } from "../dispatcher/payloads"; | ||||
| 
 | ||||
| // TODO: migrate from sync_state to MatrixActions.sync so that more js-sdk events
 | ||||
| //       become dispatches in the same place.
 | ||||
| /** | ||||
|  * Create a MatrixActions.sync action that represents a MatrixClient `sync` event, | ||||
|  * each parameter mapping to a key-value in the action. | ||||
|  |  | |||
|  | @ -1523,13 +1523,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> { | |||
|         }); | ||||
| 
 | ||||
|         cli.on('sync', (state: SyncState, prevState?: SyncState, data?: ISyncStateData) => { | ||||
|             // LifecycleStore and others cannot directly subscribe to matrix client for
 | ||||
|             // events because flux only allows store state changes during flux dispatches.
 | ||||
|             // So dispatch directly from here. Ideally we'd use a SyncStateStore that
 | ||||
|             // would do this dispatch and expose the sync state itself (by listening to
 | ||||
|             // its own dispatch).
 | ||||
|             dis.dispatch({ action: 'sync_state', prevState, state }); | ||||
| 
 | ||||
|             if (state === SyncState.Error || state === SyncState.Reconnecting) { | ||||
|                 if (data.error instanceof InvalidStoreError) { | ||||
|                     Lifecycle.handleInvalidStoreError(data.error); | ||||
|  |  | |||
|  | @ -879,10 +879,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> { | |||
|                     }); | ||||
|                 } | ||||
|                 break; | ||||
|             case 'sync_state': | ||||
|             case 'MatrixActions.sync': | ||||
|                 if (!this.state.matrixClientIsReady) { | ||||
|                     this.setState({ | ||||
|                         matrixClientIsReady: this.context && this.context.isInitialSyncComplete(), | ||||
|                         matrixClientIsReady: this.context?.isInitialSyncComplete(), | ||||
|                     }, () => { | ||||
|                         // send another "initial" RVS update to trigger peeking if needed
 | ||||
|                         this.onRoomViewStoreUpdate(true); | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ class LifecycleStore extends Store<ActionPayload> { | |||
|                     deferredAction: null, | ||||
|                 }); | ||||
|                 break; | ||||
|             case 'sync_state': { | ||||
|             case 'MatrixActions.sync': { | ||||
|                 if (payload.state !== 'PREPARED') { | ||||
|                     break; | ||||
|                 } | ||||
|  |  | |||
|  | @ -53,6 +53,7 @@ import { | |||
| } from "."; | ||||
| import { getCachedRoomIDForAlias } from "../../RoomAliasCache"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; | ||||
| import { PosthogAnalytics } from "../../PosthogAnalytics"; | ||||
| 
 | ||||
| interface IState {} | ||||
| 
 | ||||
|  | @ -490,6 +491,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> { | |||
|                 this.parentMap.getOrCreate(child.roomId, new Set()).add(space.roomId); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         PosthogAnalytics.instance.setProperty("numSpaces", joinedSpaces.length); | ||||
|     }; | ||||
| 
 | ||||
|     private rebuildHomeSpace = () => { | ||||
|  |  | |||
|  | @ -6249,9 +6249,9 @@ mathml-tag-names@^2.1.3: | |||
|   resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" | ||||
|   integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== | ||||
| 
 | ||||
| "matrix-analytics-events@github:matrix-org/matrix-analytics-events.git#dfa6feaa12bcfc8e99b05a148e12fff7f9d62f08": | ||||
| "matrix-analytics-events@github:matrix-org/matrix-analytics-events.git#53844e3f6f9fefa88384a996b2bf5e60bb301b94": | ||||
|   version "0.0.1" | ||||
|   resolved "https://codeload.github.com/matrix-org/matrix-analytics-events/tar.gz/dfa6feaa12bcfc8e99b05a148e12fff7f9d62f08" | ||||
|   resolved "https://codeload.github.com/matrix-org/matrix-analytics-events/tar.gz/53844e3f6f9fefa88384a996b2bf5e60bb301b94" | ||||
| 
 | ||||
| matrix-events-sdk@^0.0.1-beta.6: | ||||
|   version "0.0.1-beta.6" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Michael Telatynski
						Michael Telatynski