Een event is een keuze die jij maakte, niet iets wat er gebeurde
Elk product zendt een onbeperkt aantal dingen uit die er gebeuren: klikken, scrollbewegingen, hovers, routewijzigingen. Een event is het kleine deel daarvan waarvan jij besloot dat het een naam waard is, omdat het je iets vertelt waar je naar zou handelen. Die keuze, en niet het instrumenteren, is het eigenlijke werk.
Het praktische gevolg is dat een trackingplan een productdocument is en geen engineeringdocument. Als je niet kunt zeggen wat je anders zou doen afhankelijk van of een event afgaat, hoeft het nog niet te bestaan.
Noem events naar uitkomsten, niet naar interfaces
clicked_blue_button klopt niet meer op het moment dat design een redesign uitbrengt. report_exported overleeft dat wel, omdat het benoemt wat de gebruiker bereikte in plaats van waar hij op klikte.
Kies één conventie en houd je eraan: eerst het object, de actie in de verleden tijd, kleine letters met underscores — invite_sent, project_created, payment_failed. Consistentie telt zwaarder dan welke conventie je koos, want het zijn inconsistente namen die een eventcatalogus twee kwartalen later ondoorzoekbaar maken.
Een naamgevingsconventie die je kunt overnemen
De meeste teams hoeven geen conventie te bedenken, alleen er een op te schrijven. Deze is kort genoeg om te onthouden en streng genoeg om een catalogus doorzoekbaar te houden:
| Regel | Wel | Niet |
|---|---|---|
| Eerst het object, dan de actie | invite_sent | sent_invite |
| Verleden tijd, want het is al gebeurd | project_created | create_project |
| Kleine letters met underscores | plan_upgraded | PlanUpgraded, plan-upgraded |
| Benoem de uitkomst, niet het bedieningselement | report_exported | export_button_clicked |
| Varianten horen in properties | report_exported met format: csv | report_exported_csv |
| Geen persoonsgegevens in namen of waarden | plan: team | email: ana@acme.com |
Zet de conventie bovenaan het trackingplan en toets nieuwe events eraan zoals je code toetst aan een stijlgids. Voor een slechte naam betaal je elke keer dat iemand het event zoekt en niet vindt.
Tien tot twintig events, geen tweehonderd
De veelvoorkomende misser is alles tracken vanuit de gedachte dat data later nog van pas kan komen. Wat je krijgt is een catalogus waarin niemand de weg vindt, drie events die vrijwel hetzelfde betekenen, en geen enkele overeenstemming over welke daarvan leidend is.
Begin bij de vragen die je toch al stelt in evaluaties — komen mensen goed op weg, komen ze terug, waar geven ze het op — en instrumenteer alleen wat die vragen beantwoordt. Een trackingplan dat op één scherm past, wordt onderhouden. Een dat een heel spreadsheet vult, niet.
Een uitgewerkt voorbeeld: een trackingplan voor een B2B-SaaS-app
Zo zien twaalf events eruit voor een typisch SaaS-product dat om teams draait. Elk event bestaat omdat het een vraag beantwoordt die iemand al in een wekelijkse review stelt.
| Event | Gaat af wanneer | Belangrijkste properties | De vraag die het beantwoordt |
|---|---|---|---|
signup_completed | Het account bestaat, niet wanneer het formulier wordt verstuurd | source | Welke kanalen brengen mensen die het echt afronden? |
workspace_created | De eerste workspace wordt opgeslagen | team_size | Hoeveel aanmeldingen komen zover dat ze iets inrichten? |
teammate_invited | Er wordt een uitnodiging verstuurd | role | Verspreidt het account zich verder dan één persoon? |
invite_accepted | De uitgenodigde persoon doet mee | role | Worden uitnodigingen ook echt teamgenoten? |
integration_connected | Een koppeling slaagt | integration | Welke integraties gebruiken teams die blijven? |
project_created | Er wordt een project opgeslagen | template | Wordt het kernobject überhaupt aangemaakt? |
report_viewed | Een rapport is klaar met renderen | report_type | Waar komen mensen voor terug? |
report_exported | Het bestand is gegenereerd | format | Verlaat de output het product? |
plan_upgraded | De billing bevestigt de wijziging | from_plan, to_plan | Wat gebeurt er vlak voordat mensen meer gaan betalen? |
payment_failed | De betaalprovider meldt een mislukte betaling | reason | Hoeveel churn is onvrijwillig? |
subscription_cancelled | De opzegging gaat in | reason | Waarom vertrekken teams? |
feedback_submitted | Het feedbackformulier wordt verstuurd | category | Waar vragen gebruikers om, in hun eigen woorden? |
Twee dingen vallen op. De meeste van deze events gaan af op een uitkomst, niet op een klik: op een uitnodiging kan worden geklikt terwijl hij toch mislukt. En de billing-events gebeuren helemaal niet in de browser. Ze komen binnen via de webhooks van je betaalprovider, dus analytics die alleen in de browser meet, ziet ze nooit. Dat is prima, zolang niemand een klik op ‘Upgraden’ als omzet behandelt.
Activatie is meestal een combinatie van deze events en niet één ervan, bijvoorbeeld een aangemaakte workspace en een uitgenodigde collega in de eerste week. Kies die definitie bewust; benchmarks voor de activatiefunnel legt uit hoe.
Properties dragen het detail; events dragen het werkwoord
Weersta de neiging om per variant een apart event te maken. report_exported_csv, report_exported_pdf en report_exported_xlsx zouden één event moeten zijn, report_exported, met format als property. De vuistregel: als je de cijfers ooit bij elkaar opgeteld zou willen zien, is het één event met een property.
Houd de waarden van properties laag in cardinaliteit en stabiel. Een property met een kale URL of een vrije tekst erin is een kolom waarop je niet kunt groeperen, en daarmee is het versiering en geen data.
Fouten in event tracking die rapporten ongemerkt breken
- Afvuren op de klik in plaats van op het resultaat. Een klik op ‘Exporteren’ is geen export. Als het verzoek mislukt, heeft het event al gelogen. Verstuur uitkomst-events pas als het gelukt is.
- Dubbel afvuren in single-page apps. Een component dat opnieuw rendert of een route die twee keer mount, kan hetzelfde event twee keer versturen. Controleer een paar sessies met de hand voordat je een telling vertrouwt.
- Persoonsgegevens in properties. E-mailadressen, namen en URL's met tokens in de querystring komen in elk rapport en elke export terecht. Stuur in plaats daarvan een ID of een categorie.
- Tracken vóór toestemming. Waar de AVG geldt, hoort analytics pas te starten als de bezoeker akkoord gaat. Dat is een eigenschap van je setup en niet van elk event, dus los het één keer op, met een cookietoestemmingsbeheer dat tracking tot dan tegenhoudt.
- De betekenis van een event veranderen zonder het te hernoemen. Als
project_createdineens ook gedupliceerde projecten telt, spreken alle grafieken van vóór en na de wijziging elkaar tegen en weet niemand waarom. Een nieuwe betekenis krijgt een nieuwe naam, of een property die de twee uit elkaar houdt. - Events zonder eigenaar. Elk event in het plan heeft iemand nodig die merkt wanneer het niet meer afgaat. Events zonder eigenaar raken als eerste in verval en worden het langst vertrouwd.
Autocapture en expliciete events beantwoorden verschillende vragen
Autocapture registreert interacties met de interface zonder dat je iets hoeft te plannen, en dat is in het begin echt nuttig: het betekent dat de data voor een vraag die je nog niet had bedacht er al is, en het haalt de deploy uit de cyclus. Wat het niet kan, is jouw domein kennen. Niets in een klikstroom weet dat een abonnement is opgewaardeerd.
De werkbare opzet is allebei: autocapture voor verkennen en voor de vragen die je nog niet hebt gesteld, en een korte lijst expliciete, goed benoemde domeinevents voor de cijfers waarover je rapporteert en waarop je doelen zet.
Events achteraf definiëren
Auto-capture verandert de vraag van ‘hebben we eraan gedacht dit te instrumenteren?’ in ‘kunnen we het vinden in wat is vastgelegd?’. PulsePanda legt elke klik vast met de id, classes, zichtbare tekst, tag en positie op de pagina van het element, dus een event kan later op basis daarvan worden gedefinieerd, en de definitie geldt ook voor klikken die zijn vastgelegd voordat hij bestond. Een vraag die op donderdag opkomt, kan met de data van maandag worden beantwoord.
Wat dat betrouwbaar maakt, is een stabiel haakje in de markup. Classes veranderen bij elk redesign en zichtbare tekst bij elke tekstwijziging en vertaling. Een id op de handvol bedieningselementen die ertoe doen, verandert alleen als iemand besluit dat dat moet:
<button id="export-report">Export</button>
<button id="invite-teammate">Invite</button>
<a id="upgrade-plan" href="/nl/billing">Upgrade</a>
Een event dat is gedefinieerd als klikken op #export-report overleeft een redesign, en een klik op het icoon of het label in de knop telt nog steeds mee, omdat het vastgelegde pad doorloopt tot het dichtstbijzijnde element met een id.
Een gedefinieerd event blijft een klik, met de beperking die hierboven is beschreven: het vertelt je dat iemand het probeerde, niet dat het werkte. Voor uitkomsten is het eerlijkste signaal vaak de pagina waar succes naartoe leidt. Een funnelstap ‘bereikte /onboarding’ na ‘bereikte /signup’ telt afgeronde aanmeldingen zonder één event.

Zo controleer je een event voordat je het vertrouwt
- Laat het zelf afgaan en zoek je eigen sessie op. Het event hoort één keer te verschijnen, met alle properties ingevuld.
- Vergelijk de telling met een bron van waarheid. Zegt de database dat er vorige week 140 projecten zijn aangemaakt en zegt analytics 95, zoek het verschil dan uit voordat iemand er een grafiek op bouwt. Adblockers, toestemming en mislukte verzoeken maken browsertellingen allemaal lager dan servertellingen. Het verschil hoort stabiel te zijn, geen verrassing.
- Bekijk een session replay waarin het afging. Een getal vertelt je dat het gebeurde; een opname vertelt je dat het gebeurde op het moment dat jij denkt.
- Zet het in een funnel. Een event dat opduikt zonder de stap die ervoor moet komen, wordt vanaf de verkeerde plek afgevuurd.
Waar je deze week begint
Schrijf de vijf momenten op die er in jouw product het meest toe doen, geef ze een naam volgens de conventie hierboven, en instrumenteer alleen die. Controleer een week later of elk event afgaat wanneer je dat verwacht en of de properties gevuld zijn — een event dat afgaat op een codepad dat niemand gebruikt is erger dan geen event, want er zal op vertrouwd worden.
Wil je zien hoe de events die je al verstuurt zich gedragen voordat je er meer toevoegt, dan laat event tracking in PulsePanda elk event, het volume en de properties op één plek zien, en voert dezelfde data rechtstreeks door naar funnels en paden.