diff --git a/explorer/Explorer.tsx b/explorer/Explorer.tsx index a9f48821bf..e3bdeda19f 100644 --- a/explorer/Explorer.tsx +++ b/explorer/Explorer.tsx @@ -27,6 +27,7 @@ import { SlideShowController, SlideShowManager, DEFAULT_GRAPHER_ENTITY_TYPE, + GrapherAnalytics, } from "@ourworldindata/grapher" import { Bounds, @@ -189,6 +190,8 @@ export class Explorer EntityPickerManager, GrapherManager { + analytics = new GrapherAnalytics() + // caution: do a ctrl+f to find untyped usages static renderSingleExplorerOnExplorerPage( program: ExplorerProps, @@ -272,6 +275,24 @@ export class Explorer return new Map(arr.map((config) => [config.id!, config])) } + private setUpIntersectionObserver(): void { + if (typeof window !== "undefined" && "IntersectionObserver" in window) { + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + this.analytics.logExplorerView( + this.explorerProgram.slug, + this.explorerProgram.decisionMatrix.currentParams + ) + observer.disconnect() + } + }) + }) + observer.observe(this.grapherContainerRef.current!) + this.disposers.push(() => observer.disconnect()) + } + } + disposers: (() => void)[] = [] componentDidMount() { this.setGrapher(this.grapherRef!.current!) @@ -291,6 +312,7 @@ export class Explorer this.grapher?.populateFromQueryParams(url.queryParams) exposeInstanceOnWindow(this, "explorer") + this.setUpIntersectionObserver() this.attachEventListeners() this.updateEntityPickerTable() // call for the first time to initialize EntityPicker } @@ -415,6 +437,11 @@ export class Explorer : tabsWithoutTable[0] ?? GrapherTabOption.table this.grapher.populateFromQueryParams(newGrapherParams) + + this.analytics.logExplorerView( + this.explorerProgram.slug, + this.explorerProgram.decisionMatrix.currentParams + ) } @action.bound private setGrapherTable(table: OwidTable) { diff --git a/packages/@ourworldindata/grapher/src/core/GrapherAnalytics.ts b/packages/@ourworldindata/grapher/src/core/GrapherAnalytics.ts index bbaf5234f4..2f81bb6ead 100644 --- a/packages/@ourworldindata/grapher/src/core/GrapherAnalytics.ts +++ b/packages/@ourworldindata/grapher/src/core/GrapherAnalytics.ts @@ -15,6 +15,7 @@ export enum EventCategory { GrapherView = "owid.grapher_view", GrapherClick = "owid.grapher_click", GrapherError = "owid.grapher_error", + ExplorerView = "owid.explorer_view", ExplorerCountrySelector = "owid.explorer_country_selector", Hover = "owid.hover", KeyboardShortcut = "owid.keyboard_shortcut", @@ -50,6 +51,8 @@ interface GAEvent { eventTarget?: string grapherPath?: string grapherView?: string // specifies a view in a multi-dim data page + explorerPath?: string + explorerView?: string } // taken from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/de66435d18fbdb2684947d16b5cd3a77f876324c/types/gtag.js/index.d.ts#L151-L156 @@ -97,6 +100,14 @@ export class GrapherAnalytics { }) } + logExplorerView(slug: string, view: Record): void { + this.logToGA({ + event: EventCategory.ExplorerView, + explorerPath: `/explorers/${slug}`, + explorerView: JSON.stringify(view), + }) + } + logGlobalEntitySelector(action: entityControlEvent, note?: string): void { this.logToGA({ event: EventCategory.GlobalEntitySelectorUsage,