diff --git a/package-lock.json b/package-lock.json index 39803a1f..88221f91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.2.0", "license": "ISC", "dependencies": { + "@amplitude/analytics-browser": "^2.3.8", "@navikt/aksel-icons": "5.11.2", "@navikt/ds-css": "5.11.1", "@navikt/ds-react": "5.11.1", @@ -163,6 +164,95 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@amplitude/analytics-browser": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.3.8.tgz", + "integrity": "sha512-K+12aAVJPzAtWIi8Ok5Q5dvg7v7IF4G0cI8PW0COWo3uTyY103r45OcpgrpRVpVAr+41d1eiMo36jqOke89uPA==", + "dependencies": { + "@amplitude/analytics-client-common": "^2.0.10", + "@amplitude/analytics-core": "^2.1.3", + "@amplitude/analytics-types": "^2.3.1", + "@amplitude/plugin-page-view-tracking-browser": "^2.0.18", + "@amplitude/plugin-web-attribution-browser": "^2.0.18", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@amplitude/analytics-client-common": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-client-common/-/analytics-client-common-2.0.10.tgz", + "integrity": "sha512-IaERGgBN3dmCGFbFd7SFTpTBguJIQzE/uDK44KEnLj0qw9wdoTxpLhoXQpqe5WKWsr46eONL9ROCJybHs4Efnw==", + "dependencies": { + "@amplitude/analytics-connector": "^1.4.8", + "@amplitude/analytics-core": "^2.1.3", + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-client-common/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@amplitude/analytics-connector": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-connector/-/analytics-connector-1.5.0.tgz", + "integrity": "sha512-T8mOYzB9RRxckzhL0NTHwdge9xuFxXEOplC8B1Y3UX3NHa3BLh7DlBUZlCOwQgMc2nxDfnSweDL5S3bhC+W90g==" + }, + "node_modules/@amplitude/analytics-core": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-2.1.3.tgz", + "integrity": "sha512-WHXf9g33t63jYy4a/1uOpq/zHPMfEj5N2HHgJrg7Eu7v4w3kOWtPSMPBAllzFWxC5Ay5HeR9n0hqlJG0yffQWg==", + "dependencies": { + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/analytics-core/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@amplitude/analytics-types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-types/-/analytics-types-2.3.1.tgz", + "integrity": "sha512-yojBG20qvph0rpCJKb4i/FJa+otqLINEwv//hfzvjnCOcPPyS0YscI8oiRBM0rG7kZIDgaL9a6jPwkqK4ACmcw==" + }, + "node_modules/@amplitude/plugin-page-view-tracking-browser": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.0.18.tgz", + "integrity": "sha512-s7PkGOgrx6U06/emzM8k+KRGDuyP9Z2L4OyGdeQwJcURJjiZDVQsmKlTZ5/SeGvxHYgq/4QJYUmMSmzByiGTCA==", + "dependencies": { + "@amplitude/analytics-client-common": "^2.0.10", + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/plugin-page-view-tracking-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@amplitude/plugin-web-attribution-browser": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-attribution-browser/-/plugin-web-attribution-browser-2.0.18.tgz", + "integrity": "sha512-mPlXu0fEYCCXhT6WpNJoM0FYkp+HIEm7L+KBEa2IHd3GD3+mh2AVDkZmgXLl3LKb++HY8mCiqC5/NcJ2AzTNhA==", + "dependencies": { + "@amplitude/analytics-client-common": "^2.0.10", + "@amplitude/analytics-core": "^2.1.3", + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + } + }, + "node_modules/@amplitude/plugin-web-attribution-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -16896,6 +16986,105 @@ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "dev": true }, + "@amplitude/analytics-browser": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.3.8.tgz", + "integrity": "sha512-K+12aAVJPzAtWIi8Ok5Q5dvg7v7IF4G0cI8PW0COWo3uTyY103r45OcpgrpRVpVAr+41d1eiMo36jqOke89uPA==", + "requires": { + "@amplitude/analytics-client-common": "^2.0.10", + "@amplitude/analytics-core": "^2.1.3", + "@amplitude/analytics-types": "^2.3.1", + "@amplitude/plugin-page-view-tracking-browser": "^2.0.18", + "@amplitude/plugin-web-attribution-browser": "^2.0.18", + "tslib": "^2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, + "@amplitude/analytics-client-common": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-client-common/-/analytics-client-common-2.0.10.tgz", + "integrity": "sha512-IaERGgBN3dmCGFbFd7SFTpTBguJIQzE/uDK44KEnLj0qw9wdoTxpLhoXQpqe5WKWsr46eONL9ROCJybHs4Efnw==", + "requires": { + "@amplitude/analytics-connector": "^1.4.8", + "@amplitude/analytics-core": "^2.1.3", + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, + "@amplitude/analytics-connector": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-connector/-/analytics-connector-1.5.0.tgz", + "integrity": "sha512-T8mOYzB9RRxckzhL0NTHwdge9xuFxXEOplC8B1Y3UX3NHa3BLh7DlBUZlCOwQgMc2nxDfnSweDL5S3bhC+W90g==" + }, + "@amplitude/analytics-core": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-2.1.3.tgz", + "integrity": "sha512-WHXf9g33t63jYy4a/1uOpq/zHPMfEj5N2HHgJrg7Eu7v4w3kOWtPSMPBAllzFWxC5Ay5HeR9n0hqlJG0yffQWg==", + "requires": { + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, + "@amplitude/analytics-types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-types/-/analytics-types-2.3.1.tgz", + "integrity": "sha512-yojBG20qvph0rpCJKb4i/FJa+otqLINEwv//hfzvjnCOcPPyS0YscI8oiRBM0rG7kZIDgaL9a6jPwkqK4ACmcw==" + }, + "@amplitude/plugin-page-view-tracking-browser": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.0.18.tgz", + "integrity": "sha512-s7PkGOgrx6U06/emzM8k+KRGDuyP9Z2L4OyGdeQwJcURJjiZDVQsmKlTZ5/SeGvxHYgq/4QJYUmMSmzByiGTCA==", + "requires": { + "@amplitude/analytics-client-common": "^2.0.10", + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, + "@amplitude/plugin-web-attribution-browser": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-attribution-browser/-/plugin-web-attribution-browser-2.0.18.tgz", + "integrity": "sha512-mPlXu0fEYCCXhT6WpNJoM0FYkp+HIEm7L+KBEa2IHd3GD3+mh2AVDkZmgXLl3LKb++HY8mCiqC5/NcJ2AzTNhA==", + "requires": { + "@amplitude/analytics-client-common": "^2.0.10", + "@amplitude/analytics-core": "^2.1.3", + "@amplitude/analytics-types": "^2.3.1", + "tslib": "^2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, "@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", diff --git a/package.json b/package.json index 50bb247d..8d51305d 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "author": "DigiSyfo ", "license": "ISC", "dependencies": { + "@amplitude/analytics-browser": "2.3.8", "@navikt/aksel-icons": "5.11.2", "@navikt/ds-css": "5.11.1", "@navikt/ds-react": "5.11.1", diff --git a/src/components/NavigationBar.tsx b/src/components/NavigationBar.tsx index 988778c9..ad2a8772 100644 --- a/src/components/NavigationBar.tsx +++ b/src/components/NavigationBar.tsx @@ -7,7 +7,7 @@ import { minOversiktRoutePathRoutePath, } from '@/routers/AppRouter'; -const tekster = { +const texts = { enhetensOversikt: 'Enhetens oversikt', minOversikt: 'Min oversikt', }; @@ -68,13 +68,13 @@ export const NavigationBar = (): ReactElement => { className={({ isActive }) => (isActive ? 'active' : '')} to={minOversiktRoutePathRoutePath} > - {tekster.minOversikt} + {texts.minOversikt} (isActive ? 'active' : '')} to={enhetOversiktRoutePath} > - {tekster.enhetensOversikt} + {texts.enhetensOversikt}
diff --git a/src/containers/OversiktContainer.tsx b/src/containers/OversiktContainer.tsx index 51ee32d4..c2fcc305 100644 --- a/src/containers/OversiktContainer.tsx +++ b/src/containers/OversiktContainer.tsx @@ -9,6 +9,8 @@ import { NavigationBar } from '@/components/NavigationBar'; import { useTabType } from '@/context/tab/TabTypeContext'; import { NotificationBar } from '@/components/error/NotificationBar'; import ErrorBoundary from '@/components/error/ErrorBoundary'; +import * as Amplitude from '@/utils/amplitude'; +import { EventType } from '@/utils/amplitude'; const Container = styled.div` display: flex; @@ -21,13 +23,29 @@ interface Props { tabType: OverviewTabType; } +function logPageView(tab: OverviewTabType) { + Amplitude.logEvent({ + type: EventType.PageView, + data: { url: window.location.href, sidetittel: toReadableString(tab) }, + }); +} + +function toReadableString(overviewTabType: OverviewTabType): string { + switch (overviewTabType) { + case OverviewTabType.ENHET_OVERVIEW: + return 'Enhetens oversikt'; + case OverviewTabType.MY_OVERVIEW: + return 'Min oversikt'; + } +} + const OversiktContainer = ({ tabType }: Props): ReactElement => { const personregisterQuery = usePersonregisterQuery(); const personoversiktQuery = usePersonoversiktQuery(); const { setTabType } = useTabType(); - useEffect(() => { setTabType(tabType); + logPageView(tabType); }, [setTabType, tabType]); const ContainerContent = (): ReactElement => { diff --git a/src/utils/amplitude.ts b/src/utils/amplitude.ts new file mode 100644 index 00000000..12c0c624 --- /dev/null +++ b/src/utils/amplitude.ts @@ -0,0 +1,53 @@ +import * as amplitude from '@amplitude/analytics-browser'; +import { isProd } from '@/utils/miljoUtil'; + +/** + See documentation for naming guidelines: https://github.com/navikt/analytics-taxonomy + Other documentation on Aksel: https://aksel.nav.no/god-praksis/artikler/mal-brukeratferd-med-amplitude + */ +export enum EventType { + PageView = 'besøk', + Navigation = 'navigere', + OptionSelected = 'alternativ valgt', +} + +type EventPageView = { + type: EventType.PageView; + data: { + url: string; + sidetittel: string; + }; +}; + +type Navigation = { + type: EventType.Navigation; + data: { + lenketekst: string; + destinasjon: string; + }; +}; + +type OptionSelected = { + type: EventType.OptionSelected; + data: { + url: string; + tekst: string; + option: string; + }; +}; + +type Event = EventPageView | Navigation | OptionSelected; + +export const logEvent = (event: Event) => + amplitude.track(event.type, { ...event.data }); + +const getApiKey = () => { + return isProd() + ? 'e4b68538f8d185f0ee2d913d8e51bd39' + : 'c7bcaaf5d0fddda592412234dd3da1ba'; +}; + +amplitude.init(getApiKey(), undefined, { + serverUrl: 'https://amplitude.nav.no/collect', + defaultTracking: true, +}); diff --git a/src/utils/miljoUtil.ts b/src/utils/miljoUtil.ts index 5283c646..21de0587 100644 --- a/src/utils/miljoUtil.ts +++ b/src/utils/miljoUtil.ts @@ -9,6 +9,10 @@ export const erLokal = (): boolean => { return window.location.host.indexOf('localhost') > -1; }; +export function isProd(): boolean { + return window.location.href.indexOf('syfooversikt.intern.nav.no') > -1; +} + export const finnNaisUrlDefault = (): string => { return erPreProd() ? '.intern.dev.nav.no' : '.intern.nav.no'; }; diff --git a/test/setup.tsx b/test/setup.tsx index 2a65d614..8641db5d 100644 --- a/test/setup.tsx +++ b/test/setup.tsx @@ -23,18 +23,20 @@ function copyProps(src: any, target: any) { Object.defineProperties(target, propsAsPropertyDescriptorMap); } -let temp: any = null; -const localS = { - getItem() { - return temp; - }, - setItem(key: any, value: any) { - temp = value; - }, -}; +function localStorage() { + let storage = {}; + return { + getItem: function (key: string) { + return key in storage ? (storage as any)[key] : null; + }, + setItem: function (key: string, value: any) { + (storage as any)[key] = value || ''; + }, + }; +} (global as any).HTMLElement = window.HTMLElement; -(global as any).localStorage = localS; +(global as any).localStorage = localStorage(); (global as any).XMLHttpRequest = window.XMLHttpRequest; (global as any).window = window;