Hoe we omgaan met kapotte Matomo heatmap-screenshots

Heatmap-screenshots gaan stuk op de meeste moderne sites door de manier waarop Matomo de DOM serialiseert en opnieuw rendert. Dit zijn de patronen waar we steeds tegenaan liepen, en een kleine open source extensie die we gebouwd hebben om ze op te lossen.

Als je ooit een Matomo heatmap hebt geopend en een leeg vlak zag waar je hero-afbeelding hoort te staan, of een productoverzicht dat afsnijdt na de eerste rij, of een sticky header die dwars over de pagina-inhoud valt — je bent niet de eerste. Heatmap-screenshots gaan stuk op de meeste moderne websites. De oorzaak is structureel, niet iets wat je oplost door je trackingconfiguratie bij te stellen.

Matomo's trackingscript serialiseert de DOM van je pagina naar HTML en stuurt die naar je Matomo-server. De server rendert die HTML vervolgens opnieuw, in een volledig andere context, om de screenshot te produceren die je te zien krijgt. Geen cookies. Geen sessie. Andere origin. Niks van de runtime die je JavaScript-framework heeft opgezet. Een hoop dingen die werkten omdat ze in een echte browser draaiden, mislukken stilletjes als diezelfde HTML koud elders opnieuw wordt gerenderd.

Zodra je dat ziet, begint de lijst met bugs logisch te worden.

De patronen waar we steeds tegenaan lopen

De meeste sites hebben last van minimaal drie hiervan. Sommige van alle zes.

  • CORS blokkeert je CDN-afbeeldingen en -lettertypen, omdat de Matomo-server geen inloggegevens heeft voor jouw domein. Afbeeldingen verschijnen als kapotte icoontjes. Lettertypen vallen terug op systeemstandaarden.
  • Scrollcontainers (overflow: hidden of overflow: auto met een vaste hoogte) knippen alles af onder hun zichtbare gebied. Matomo serialiseert de DOM in zijn huidige staat, dus wat niet op scherm was tijdens het vastleggen zit niet in de snapshot.
  • Sticky en fixed headers klappen in op de content eronder. Hun posities worden berekend ten opzichte van een viewport, en server-side is er geen viewport, dus zakken ze naar waar ze in de DOM staan.
  • Relatieve URL's zoals /images/hero.jpg worden opgelost ten opzichte van de Matomo-server in plaats van die van jou. Het bestand bestaat daar niet, dus het mislukt stilletjes.
  • Aangepaste lettertypen die via @font-face worden geladen, vallen terug op systeemstandaarden als de lettertypebestanden CORS-beveiligd zijn of de user-agent van de Matomo-server blokkeren.
  • Single-page apps worden vastgelegd voordat React of Vue klaar zijn met renderen, waardoor de helft van de pagina ontbreekt in de snapshot.

De meeste van deze problemen hebben een oplossing op infrastructuurniveau. CORS-headers toevoegen op je CDN. Overstappen op absolute URL's. Een matomoHeatmap CSS-hook gebruiken om sticky positionering tijdens het vastleggen te overschrijven. Matomo's eigen documentatie behandelt er een aantal van, en we hebben een uitgebreidere post geschreven die elk probleem en de server-side oplossing doorloopt als dat de route is die je wilt nemen.

Het nadeel is dat het werk verspreid raakt over CDN-configuratie, CSS en je trackingsetup, en sommige dingen kun je helemaal niet oplossen als je de assets niet beheert. We liepen vaak genoeg tegen die muur op bij klanten, dus we zijn uiteindelijk iets anders gaan doen.

Wat we uiteindelijk gebouwd hebben

We begonnen met een klein script dat we voor elke capture in DevTools plakten. Het embedde afbeeldingen en lettertypen als data-URI's, breidde scrollcontainers uit, maakte headers los, herschreef relatieve URL's naar absolute. Na verloop van tijd groeide het uit tot een Chrome-extensie die we intern bij elke klant gebruikten.

Dat is Matomo Heatmap Helper. We hebben het open source gemaakt.

De setup past op één scherm. Je voert je Matomo-URL in, een API-token, en kiest voor welke sites je de werkbalk wilt weergeven. Op elke overeenkomende pagina verschijnt een kleine balk.

Het echte werk gebeurt op het moment van vastleggen. Als je op de screenshotknop drukt, doet de extensie de dingen die statisch tijdrovend zijn. Het embedt afbeeldingen en lettertypen als base64 data-URI's zodat de Matomo-server nooit iets cross-origin hoeft op te halen. Het breidt scrollcontainers uit naar hun volledige contenthoogte. Het zet sticky en fixed headers om naar de normale flow. Het herschrijft relatieve URL's naar absolute, past het formaat van iframes aan, pauzeert video's naar frame nul, en geeft SPA-content de tijd om te renderen. Dan roept het Matomo's screenshot-API aan, wacht op het resultaat, en draait elke wijziging terug. Je live pagina gaat weer terug naar hoe die was.

De reden dat dit werkt: je kunt met elementen interacteren vóór het vastleggen. Aangepaste scrollcontainers, een lastige sticky header, een sectie waar assets niet laden — je klikt ze aan in de interactieve modus, ze krijgen een slotpictogram, en de pipeline weet wat er mee moet gebeuren. Het trackingscript alleen kan dat niet, omdat het vastlegt in welke staat de DOM toevallig was op het moment dat het werd uitgevoerd. Door een persoon de extensie te laten vertellen welke elementen aandacht nodig hebben, los je de gevallen op die het script nooit kon oplossen.

De extensie communiceert alleen met je eigen Matomo-instantie. Je API-token wordt opgeslagen in chrome.storage.local, afgeschermd van de pagina's die je bezoekt. Geen telemetrie, geen gebruiksmonitoring. De code staat op GitHub. Issues en pull requests zijn welkom.

Waarom we het uitgebracht hebben

Als officieel Matomo Partner bureau liepen we bij bijna elk klanttraject tegen kapotte heatmaps aan. De events werden correct bijgehouden, maar de screenshots waren onbruikbaar — en dat is nou juist het onderdeel waar de meeste stakeholders naar kijken.

Matomo heeft ons als bureau veel gegeven. We gebruiken de extensie dagelijks voor klantwerk en blijven randgevallen verbeteren die we op websites tegenkomen. Als je nog onopgeloste heatmap-problemen tegenkomt, open dan een GitHub-issue en we kijken of we een fix aan de extensie kunnen toevoegen.

Waar we aan werken

Matomo Heatmap Helper is voortgekomen uit een groter project. Martez verbindt Matomo met Meta Ads en Google Ads, zodat ROAS, CLV en multi-touch attributie naast je webanalytics staan in plaats van in een apart spreadsheet. Het zit in private beta. Als dat relevant voor je is, kun je je inschrijven voor de wachtlijst.

Hoe dan ook, de heatmap-extensie is zijn eigen ding en blijft dat ook. We hebben het gebouwd omdat we het nodig hadden.

Hoe we omgaan met kapotte Matomo heatmap-screenshots - Martez Blog