From 88dd7cd763c47b50aa3e545aeea0e4c5c87baab9 Mon Sep 17 00:00:00 2001 From: Aric Lasry Date: Sat, 9 Mar 2024 23:12:17 +0100 Subject: [PATCH] [Amplitude] Page view and session tracking client side --- .vscode/settings.json | 4 +- front/components/sparkle/AppLayout.tsx | 14 ++++++ .../lib/amplitude/browser/generated/index.ts | 50 +++++++++++++++++++ front/lib/amplitude/browser/index.ts | 8 ++- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 13771d5a0a044..c949f5df78054 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,8 +3,8 @@ "rust-analyzer.linkedProjects": ["./core/Cargo.toml"], "editor.codeActionsOnSave": { - "source.organizeImports": false, - "source.fixAll.eslint": true + "source.organizeImports": "never", + "source.fixAll.eslint": "explicit" }, "eslint.run": "onSave", "typescript.preferences.importModuleSpecifier": "non-relative" diff --git a/front/components/sparkle/AppLayout.tsx b/front/components/sparkle/AppLayout.tsx index edac39130ece4..103ade14481b5 100644 --- a/front/components/sparkle/AppLayout.tsx +++ b/front/components/sparkle/AppLayout.tsx @@ -24,6 +24,7 @@ import type { } from "@app/components/sparkle/navigation"; import { topNavigation } from "@app/components/sparkle/navigation"; import WorkspacePicker from "@app/components/WorkspacePicker"; +import { getBrowserClient } from "@app/lib/amplitude/browser"; import { useUser } from "@app/lib/swr"; import { classNames } from "@app/lib/utils"; @@ -243,11 +244,24 @@ export default function AppLayout({ }) { const { sidebarOpen, setSidebarOpen } = useContext(SidebarContext); const [loaded, setLoaded] = useState(false); + const router = useRouter(); + const user = useUser(); useEffect(() => { setLoaded(true); }, []); + useEffect(() => { + const amplitude = getBrowserClient(); + if (user?.user?.id) { + const userId = `user-${user?.user?.id}`; + amplitude.identify(userId); + amplitude.pageViewed({ + pathname: router.pathname, + }); + } + }, [router.pathname, user?.user?.id]); + return ( <> diff --git a/front/lib/amplitude/browser/generated/index.ts b/front/lib/amplitude/browser/generated/index.ts index c28cc687b7a25..9bf4e89b52c61 100644 --- a/front/lib/amplitude/browser/generated/index.ts +++ b/front/lib/amplitude/browser/generated/index.ts @@ -63,6 +63,15 @@ export type LoadOptions = | LoadOptionsWithApiKey | LoadOptionsWithClientInstance; +export interface IdentifyProperties { + email?: string; + SignupDate?: string; +} + +export interface PageViewedProperties { + pathname: string; +} + export interface QuickGuideViewedProperties { /** * | Rule | Value | @@ -74,6 +83,22 @@ export interface QuickGuideViewedProperties { workspaceName: string; } +export class Identify implements BaseEvent { + event_type = amplitude.Types.SpecialEventType.IDENTIFY; + + constructor(public event_properties?: IdentifyProperties) { + this.event_properties = event_properties; + } +} + +export class PageViewed implements BaseEvent { + event_type = "PageViewed"; + + constructor(public event_properties: PageViewedProperties) { + this.event_properties = event_properties; + } +} + export class QuickGuideViewed implements BaseEvent { event_type = "QuickGuideViewed"; @@ -145,10 +170,12 @@ export class Ampli { * Identify a user and set user properties. * * @param userId The user's id. + * @param properties The user properties. * @param options Optional event options. */ identify( userId: string | undefined, + properties?: IdentifyProperties, options?: EventOptions, ): PromiseResult { if (!this.isInitializedAndEnabled()) { @@ -160,6 +187,12 @@ export class Ampli { } const amplitudeIdentify = new amplitude.Identify(); + const eventProperties = properties; + if (eventProperties != null) { + for (const [key, value] of Object.entries(eventProperties)) { + amplitudeIdentify.set(key, value); + } + } return this.amplitude!.identify( amplitudeIdentify, options, @@ -191,6 +224,23 @@ export class Ampli { return this.amplitude!.track(event, undefined, options); } + /** + * PageViewed + * + * [View in Tracking Plan](https://data.amplitude.com/dust-tt/dust-prod/events/main/latest/PageViewed) + * + * Event has no description in tracking plan. + * + * @param properties The event's properties (e.g. pathname) + * @param options Amplitude event options. + */ + pageViewed( + properties: PageViewedProperties, + options?: EventOptions, + ) { + return this.track(new PageViewed(properties), options); + } + /** * QuickGuideViewed * diff --git a/front/lib/amplitude/browser/index.ts b/front/lib/amplitude/browser/index.ts index 6baa821cda109..83140e85f3feb 100644 --- a/front/lib/amplitude/browser/index.ts +++ b/front/lib/amplitude/browser/index.ts @@ -18,7 +18,13 @@ export function getBrowserClient() { client: { apiKey: AMPLITUDE_PUBLIC_API_KEY, configuration: { - defaultTracking: false, + defaultTracking: { + attribution: true, + fileDownloads: false, + formInteractions: true, + pageViews: false, + sessions: true, + }, }, }, });