So gehen wir mit fehlerhaften Matomo-Heatmap-Screenshots um

Heatmap-Screenshots gehen auf den meisten modernen Websites kaputt, weil Matomo das DOM serialisiert und anderswo neu rendert. Hier sind die Muster, auf die wir immer wieder gestoßen sind, und eine kleine Open-Source-Erweiterung, die wir gebaut haben, um damit umzugehen.

Wenn du schon mal eine Matomo-Heatmap geöffnet hast und statt deines Hero-Bilds ein leeres Rechteck siehst, oder ein Produktraster, das nach der ersten Reihe abschneidet, oder einen Sticky-Header, der quadratisch auf dem Seiteninhalt sitzt – du bist nicht die erste Person, der das passiert. Heatmap-Screenshots gehen auf den meisten modernen Websites out of the box kaputt. Der Grund ist struktureller Natur, nichts, das du durch Anpassungen an deiner Tracking-Konfiguration behebst.

Matomos Tracking-Skript serialisiert das DOM deiner Seite in HTML und schickt es an deinen Matomo-Server. Der rendert dieses HTML dann erneut, in einem komplett anderen Kontext, um den Screenshot zu erzeugen, den du siehst. Keine Cookies. Keine Session. Anderer Origin. Nichts von dem, was dein JavaScript-Framework zur Laufzeit aufgebaut hat. Vieles, das funktioniert hat, weil es in einem echten Browser lief, schlägt stillschweigend fehl, wenn dasselbe HTML kalt irgendwo anders neu gerendert wird.

Wenn man das einmal verstanden hat, ergibt die Fehlerliste auf einmal Sinn.

Die Muster, auf die wir immer wieder stoßen

Die meisten Seiten treffen mindestens drei davon. Manche alle sechs.

  • CORS blockiert deine CDN-gehosteten Bilder und Schriftarten, weil der Matomo-Server keine Zugangsdaten für deine Domain hat. Bilder kommen als kaputte Symbole zurück. Schriftarten fallen auf Systemschriften zurück.
  • Scroll-Container (overflow: hidden oder overflow: auto mit fester Höhe) schneiden alles ab, was sich unterhalb des sichtbaren Bereichs befindet. Matomo serialisiert das DOM in seinem aktuellen Zustand, also ist alles, was zum Erfassungszeitpunkt nicht auf dem Bildschirm war, nicht im Snapshot.
  • Sticky- und fixed Header kollabieren auf den darunterliegenden Inhalt. Ihre Positionen werden relativ zum Viewport berechnet, und serverseitig gibt es keinen Viewport, also fallen sie auf die Stelle im DOM zurück, an der sie stehen.
  • Relative URLs wie /images/hero.jpg werden gegen den Matomo-Server aufgelöst statt gegen deinen. Die Datei existiert dort nicht, also schlägt das einfach still fehl.
  • Benutzerdefinierte Schriftarten, die über @font-face geladen werden, fallen auf Systemschriften zurück, wenn die Schriftdateien per CORS geschützt sind oder den User-Agent des Matomo-Servers blockieren.
  • Single-Page-Apps werden erfasst, bevor React oder Vue fertig gerendert haben, sodass die Hälfte der Seite im Snapshot fehlt.

Die meisten davon haben Lösungen auf Infrastrukturebene. CORS-Header auf deinem CDN setzen. Auf absolute URLs wechseln. Einen matomoHeatmap-CSS-Hook verwenden, um Sticky-Positionierung während der Erfassung zu überschreiben. Matomos eigene Dokumentation behandelt mehrere davon, und wir haben einen längeren Beitrag geschrieben, der jedes Problem und seine serverseitige Lösung durchgeht, falls das dein Weg ist.

Der Haken: Die Arbeit verteilt sich auf CDN-Konfiguration, CSS und dein Tracking-Setup, und manches davon kann man überhaupt nicht fixen, wenn man die Assets nicht kontrolliert. Wir sind auf genug Client-Seiten gegen diese Wand gelaufen, dass wir am Ende einen anderen Weg gegangen sind.

Was wir letztendlich gebaut haben

Wir haben mit einem kleinen Skript angefangen, das wir vor jeder Erfassung in DevTools eingefügt haben. Es hat Bilder und Schriftarten als Data-URIs eingebettet, Scroll-Container aufgeklappt, Header entfixiert, relative URLs in absolute umgeschrieben. Mit der Zeit wurde daraus eine Chrome-Erweiterung, die wir intern für jeden Client genutzt haben.

Das ist Matomo Heatmap Helper. Wir haben ihn als Open Source veröffentlicht.

Die Einrichtung ist ein einziger Bildschirm. Du gibst deine Matomo-URL, ein API-Token ein und wählst aus, auf welchen Seiten die Toolbar erscheinen soll. Auf jeder passenden Seite taucht eine kleine Leiste auf.

Die Arbeit passiert zum Erfassungszeitpunkt. Wenn du den Screenshot-Button drückst, erledigt die Erweiterung die Dinge, die statisch aufwendig zu machen sind. Sie bettet Bilder und Schriftarten als Base64-Data-URIs ein, sodass der Matomo-Server nichts mehr Cross-Origin abrufen muss. Sie klappt Scroll-Container auf ihre volle Inhaltshöhe auf. Sie wandelt Sticky- und fixed Header in normalen Fluss um. Sie schreibt relative URLs in absolute um, passt iframes an, pausiert Videos auf Frame null und gibt SPA-Inhalten Zeit zum Rendern. Dann ruft sie Matomos Screenshot-API auf, wartet auf das Ergebnis und macht jede Änderung rückgängig. Deine Live-Seite geht wieder in den Zustand zurück, in dem sie war.

Der Grund, warum das funktioniert: Du kannst mit Elementen interagieren, bevor die Erfassung läuft. Benutzerdefinierte Scroll-Container, ein störender Sticky-Header, ein Bereich, in dem Assets nicht laden – du klickst sie im Interactive-Modus an, sie bekommen ein Schloss-Symbol, und die Pipeline weiß, was damit zu tun ist. Das Tracking-Skript allein kann das nicht, weil es einfach den Zustand des DOMs erfasst, in dem es sich zum Zeitpunkt der Ausführung befand. Dass eine Person der Erweiterung sagen kann, welche Elemente behandelt werden müssen, ist das, was die Fälle behebt, die das Skript nie hätte lösen können.

Die Erweiterung redet nur mit deiner Matomo-Instanz. Dein API-Token liegt in chrome.storage.local, das von den Seiten isoliert ist, die du besuchst. Kein Telemetry, kein Usage-Tracking. Der Code ist auf GitHub. Issues und Pull Requests sind willkommen.

Warum wir das veröffentlicht haben

Als offiziell zertifizierte Matomo-Partner-Agentur waren kaputte Heatmaps ein Problem, auf das wir bei fast jedem Client-Projekt gestoßen sind. Die Events wurden korrekt getrackt, aber die Screenshots waren unbrauchbar – und das ist genau der Teil, den die meisten Stakeholder sich ansehen.

Matomo hat uns als Agentur viel gegeben. Wir verwenden die Erweiterung täglich bei der Client-Arbeit und verbessern weiterhin Edge Cases, die wir auf Websites entdecken. Wenn du auf ungelöste Heatmap-Probleme stößt, öffne bitte ein GitHub-Issue und wir schauen, ob wir einen Fix in die Erweiterung einbauen können.

Woran wir gerade arbeiten

Matomo Heatmap Helper ist aus einem größeren Projekt heraus entstanden. Martez verbindet Matomo mit Meta Ads und Google Ads, sodass ROAS, CLV und Multi-Touch-Attribution direkt neben deinen Web-Analytics liegen statt in einer separaten Tabelle. Es ist in der Private Beta. Wenn das für dich relevant ist, kannst du dich auf die Warteliste eintragen.

So oder so ist die Heatmap-Erweiterung ihr eigenes Ding, und das bleibt so. Wir haben sie gebaut, weil wir sie gebraucht haben.

So gehen wir mit fehlerhaften Matomo-Heatmap-Screenshots um - Martez Blog