Skip to content

Commit

Permalink
Merge pull request #314 from navikt/sette-opp-amplitude
Browse files Browse the repository at this point in the history
Sette opp amplitude og tracke arbeidslista
  • Loading branch information
JulieHillRoa committed Sep 29, 2023
2 parents 122f092 + 20d96bd commit 34f59ed
Show file tree
Hide file tree
Showing 11 changed files with 453 additions and 122 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-dev-gcp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Run tests
run: npm run test
- name: Build application
run: npm run build
run: npm run build:dev
env:
PUBLIC_URL: https://veilarbvisittkortfs.intern.dev.nav.no
- name: Authenticate to Google Cloud
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/depoloy-prod-gcp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Run tests
run: npm run test
- name: Build application
run: npm run build
run: npm run build:prod
env:
PUBLIC_URL: https://veilarbvisittkortfs.intern.nav.no
- name: Authenticate to Google Cloud
Expand Down
450 changes: 342 additions & 108 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
"version": "0.1.0",
"private": true,
"scripts": {
"start": "cross-env REACT_APP_DEV=true craco start",
"build": "craco build",
"build:mock": "cross-env PUBLIC_URL=/veilarbvisittkortfs REACT_APP_DEV=true craco build",
"start": "cross-env REACT_APP_MOCK=true craco start",
"build:dev": "cross-env REACT_APP_DEPLOYMENT_ENV=development craco build",
"build:prod": "cross-env REACT_APP_DEPLOYMENT_ENV=production craco build",
"build:mock": "cross-env PUBLIC_URL=/veilarbvisittkortfs REACT_APP_MOCK=true craco build",
"test": "echo not implemented",
"prettier": "prettier --write 'src/**/*.ts{,x}'",
"lint": "eslint src"
Expand All @@ -31,6 +32,7 @@
]
},
"dependencies": {
"@amplitude/analytics-browser": "2.3.2",
"@navikt/ds-css": "1.3.0",
"@navikt/ds-css-internal": "1.3.0",
"@navikt/ds-icons": "1.3.0",
Expand Down
63 changes: 63 additions & 0 deletions src/amplitude/amplitude.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as amplitude from '@amplitude/analytics-browser';
import { track } from '@amplitude/analytics-browser';
import { AmplitudeEvent } from './taxonomy-events';
import { erProd } from '../util/utils';

export function initAmplitude() {
const prosjektId = erProd() ? '691963e61d2b11465aa96acfcaa8959b' : 'faf28eb5445abfe75c7ac28ae7a8d050';

amplitude.init(prosjektId, undefined, {
serverUrl: 'https://amplitude.nav.no/collect',
ingestionMetadata: {
sourceName: window.location.origin
},
defaultTracking: false
});
}

const maskereFodselsnummer = (data?: Record<string, unknown>) => {
const maskertObjekt = JSON.stringify(data).replace(/\d{11}/g, (_, indexOfMatch, fullString) =>
fullString.charAt(indexOfMatch - 1) === '"' ? '***********' : '"***********"'
);

try {
return JSON.parse(maskertObjekt);
} catch (e) {
// eslint-disable-next-line no-console
console.error('kunne ikke maskere data korrekt før sending til amplitude');
}
return {};
};

async function logAmplitudeEvent(
eventName: string,
eventData?: Record<string, unknown>,
origin = 'veilarbvisittkortfs'
): Promise<void> {
try {
await track(eventName, { ...eventData, app: origin });
} catch (e) {
return Promise.reject(`Unexpected Amplitude error: ${e}`);
}
}

export const trackAmplitude = (event: AmplitudeEvent, ekstraData?: Record<string, unknown>): Promise<void> => {
if (!event || event.constructor !== Object) {
return Promise.reject(
'Argument must be an object of type {eventName: string, eventData?: Record<string, unknown>}'
);
}

const { name: eventName, data: eventData = {} } = event;
if (!eventName || typeof eventName !== 'string') {
return Promise.reject('Parameter "eventName" must be a string');
}
if (!eventData || eventData.constructor !== Object) {
return Promise.reject('Parameter "eventData" must be a plain object');
}
if (!!ekstraData && ekstraData?.constructor !== Object) {
return Promise.reject('Parameter "ekstraData" must be a plain object');
}

return logAmplitudeEvent(eventName, maskereFodselsnummer({ ...eventData, ...ekstraData }));
};
4 changes: 4 additions & 0 deletions src/amplitude/taxonomy-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//Før du lager en ny eventType -> sjekk https://github.com/navikt/analytics-taxonomy/tree/main/events
export type AmplitudeEvent =
| { name: 'skjema fullført'; data: { skjemanavn: string; skjemaId: string } }
| { name: 'knapp klikket'; data: { knapptekst: string; effekt: string } };
17 changes: 17 additions & 0 deletions src/component/arbeidsliste/arbeidsliste-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { kanFjerneArbeidsliste, selectSammensattNavn } from '../../util/selector
import { useModalStore } from '../../store/modal-store';
import { ifResponseHasData } from '../../util/utils';
import { logMetrikk } from '../../util/logger';
import { trackAmplitude } from '../../amplitude/amplitude';

const arbeidslisteEmptyValues = {
overskrift: '',
Expand Down Expand Up @@ -67,6 +68,22 @@ function ArbeidslisteModal() {
applikasjon: 'visittkort'
});

trackAmplitude(
{
name: 'skjema fullført',
data: {
skjemanavn: erIRedigeringModus ? 'Rediger arbeidsliste' : 'Legg til arbeidsliste',
skjemaId: 'veilarbvisittkortfs-arbeidsliste'
}
},
{
kategori: values.kategori,
overskriftslengde: values.overskrift?.length,
kommentarlengde: values.kommentar?.length,
fristSatt: !!values.frist?.length
}
);

showSpinnerModal();

const formValus: ArbeidslisteformValues = {
Expand Down
6 changes: 5 additions & 1 deletion src/component/arbeidsliste/fjern-arbeidsliste-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useDataStore } from '../../store/data-store';
import { selectSammensattNavn } from '../../util/selectors';
import { ifResponseHasData } from '../../util/utils';
import { logMetrikk } from '../../util/logger';
import { trackAmplitude } from '../../amplitude/amplitude';

function FjernArbeidslisteModal() {
const { brukerFnr } = useAppStore();
Expand All @@ -19,7 +20,10 @@ function FjernArbeidslisteModal() {

function handleSlettArbeidsListe() {
logMetrikk('visittkort.metrikker.fjern_arbeidsliste');

trackAmplitude({
name: 'knapp klikket',
data: { knapptekst: 'Fjern arbeidsliste', effekt: 'Fjern bruker fra arbeidslista' }
});
showSpinnerModal();

slettArbeidsliste(brukerFnr).then(ifResponseHasData(setArbeidsliste)).then(hideModal).catch(showErrorModal);
Expand Down
7 changes: 5 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Navspa } from '@navikt/navspa';
import { isDevelopment } from './util/utils';
import { isLocalDevelopment } from './util/utils';
import * as dayjs from 'dayjs';
import 'dayjs/locale/nb';
import App from './app';
import { initAmplitude } from './amplitude/amplitude';

dayjs.locale('nb');

Navspa.eksporter('veilarbvisittkortfs', App);

if (isDevelopment()) {
if (isLocalDevelopment()) {
require('./mock');

ReactDOM.render(
<App fnr={'10108000398'} enhet={'1234'} tilbakeTilFlate={''} visVeilederVerktoy={true} />,
document.getElementById('veilarbvisittkortfs-root')
);
} else {
initAmplitude();
}
4 changes: 2 additions & 2 deletions src/util/logger.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isDevelopment } from './utils';
import { isLocalDevelopment } from './utils';
import { sendEventTilVeilarbperson } from '../api/veilarbperson';

export interface FrontendEvent {
Expand All @@ -8,7 +8,7 @@ export interface FrontendEvent {
}

export const logMetrikk = (name: string, fields?: {}, tags?: {}): void => {
if (isDevelopment()) {
if (isLocalDevelopment()) {
// eslint-disable-next-line no-console
console.log('Event', name, 'Fields:', fields, 'Tags:', tags);
} else {
Expand Down
12 changes: 8 additions & 4 deletions src/util/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AxiosResponse } from 'axios';
import { PersonaliaTelefon } from "../api/veilarbperson";
import { StringOrNothing } from "./type/utility-types";
import { PersonaliaTelefon } from '../api/veilarbperson';
import { StringOrNothing } from './type/utility-types';

const emdashCharacterCode = 8212;
const EMDASH = String.fromCharCode(emdashCharacterCode);
Expand All @@ -12,10 +12,12 @@ export function visEmdashHvisNull(verdi: StringOrNothing) {
}
export const APP_NAME = 'veilarbvisittkortfs';

export function isDevelopment(): boolean {
return process.env.REACT_APP_DEV === 'true';
export function isLocalDevelopment(): boolean {
return process.env.REACT_APP_MOCK === 'true';
}

export const erProd = () => (process.env.REACT_APP_DEPLOYMENT_ENV as DeploymentEnvironment) === 'production';

export function ifResponseHasData<T>(
callback: (data: T) => void
): (res: AxiosResponse<T>) => Promise<AxiosResponse<T>> {
Expand Down Expand Up @@ -90,3 +92,5 @@ export function formaterTelefonnummer(telefon: PersonaliaTelefon | undefined | s

return `${landkode} ${splittTall.join(' ')}`;
}

export type DeploymentEnvironment = 'local' | 'development' | 'production';

0 comments on commit 34f59ed

Please sign in to comment.