Matomoヒートマップの壊れたスクリーンショットにどう対処しているか

ヒートマップのスクリーンショットが壊れるのは、MatomoがDOMをシリアライズして再レンダリングする仕組みに起因します。よく遭遇するパターンと、それに対処するために作った小さなオープンソース拡張機能を紹介します。

Matomoのヒートマップを開いたら、ヒーロー画像があるはずの場所が真っ白な四角になっていたり、商品グリッドが最初の行で切れていたり、スティッキーヘッダーがページコンテンツの上にどかんと乗っていたり——そんな経験があるなら、同じ目に遭っているのはあなただけではありません。ヒートマップのスクリーンショットは、ほとんどのモダンなサイトでそのままでは壊れます。原因は構造的なもので、トラッキング設定をいじって直せるものではありません。

MatomoのトラッキングスクリプトはページのDOMをHTMLにシリアライズして、Matomoサーバーに送ります。サーバーはそのHTMLを、まったく別のコンテキストで再レンダリングして、表示されるスクリーンショットを生成します。Cookieなし。セッションなし。オリジンも違う。JavaScriptフレームワークが用意したランタイムも何もない。実際のブラウザで動いていたものが、同じHTMLを別の場所でコールドレンダリングすると、静かに壊れていきます。

この仕組みさえわかれば、バグの一覧が腑に落ちてきます。

よく遭遇するパターン

ほとんどのサイトで、このうち少なくとも3つは引っかかります。6つ全部というサイトもあります。

  • CDNでホストされた画像やフォントがCORSでブロックされる。Matomoサーバーはあなたのドメインへの認証情報を持っていないため、画像は壊れたアイコンになり、フォントはシステムのデフォルトにフォールバックします。
  • スクロールコンテナ(固定の高さを持つ overflow: hiddenoverflow: auto)が、表示領域より下のものをすべてクリップします。MatomoはDOMをそのときの表示状態でシリアライズするので、キャプチャ時に画面外にあったものはスナップショットに含まれません。
  • スティッキーヘッダーや固定ヘッダーがコンテンツの下に崩れ落ちます。位置はビューポートを基準に計算されるのに、サーバー側にビューポートはないので、DOM上の位置にそのまま落ちてしまいます。
  • /images/hero.jpg のような相対URLが、あなたのサーバーではなくMatomoサーバーを基準に解決されます。そこにファイルはないので、静かに失敗します。
  • @font-face で読み込まれたカスタムフォントが、フォントファイルがCORS保護されていたりMatomoサーバーのUser-Agentをブロックしたりして、システムデフォルトにフォールバックします。
  • シングルページアプリケーションが、ReactやVueのレンダリングが終わる前にキャプチャされて、ページの半分がスナップショットから抜け落ちます。

これらのほとんどはインフラレベルで修正できます。CDNにCORSヘッダーを追加する。絶対URLに切り替える。キャプチャ中だけスティッキーのポジションを上書きするCSSフックとして matomoHeatmap クラスを使う。Matomoのドキュメントにもいくつか解説があり、サーバー側で各問題を修正する方法を順番に解説したより詳しい記事も書いています。

問題は、作業がCDN設定、CSS、トラッキング設定にまたがることと、アセットを管理していない場合はどうしても修正できないものがあることです。クライアントサイトで何度もこの壁にぶつかった結果、別のアプローチをとることにしました。

作ったもの

もともとは、キャプチャの前にDevToolsに貼り付けていた小さなスクリプトでした。画像やフォントをデータURIとして埋め込み、スクロールコンテナを展開し、ヘッダーの固定を解除し、相対URLを絶対URLに書き換えるものです。それが徐々に育って、社内でクライアントごとに使うChrome拡張機能になりました。

それがMatomo Heatmap Helperです。オープンソースとして公開しました。

セットアップは1画面で完結します。MatomoのURL、APIトークンを入力して、ツールバーを表示したいサイトを選ぶだけ。対象ページでは小さなバーが表示されます。

実際の処理はキャプチャのタイミングで行われます。スクリーンショットボタンを押すと、拡張機能が静的にやると時間のかかる処理を実行します。Matomoサーバーがクロスオリジンでフェッチしなくていいように、画像とフォントをbase64データURIとして埋め込みます。スクロールコンテナをコンテンツの全高に展開します。スティッキーヘッダーや固定ヘッダーを通常フローに変換します。相対URLを絶対URLに書き換え、iframeのサイズを調整し、動画をフレーム0で一時停止し、SPAのコンテンツがレンダリングされる時間を確保します。そのあとMatomoのスクリーンショットAPIを呼んで結果を待ち、すべての変更を元に戻します。ライブのページはもとの状態に戻ります。

これが機能する理由は、キャプチャ前に要素を操作できることにあります。カスタムスクロールコンテナ、うまく動いていないスティッキーヘッダー、アセットが読み込まれていないセクション——Interactiveモードでそれらをクリックするとロックアイコンが付き、パイプラインがどう処理するかを把握します。トラッキングスクリプト単体では、DOMがたまたまその瞬間にどんな状態だったかをキャプチャするしかありませんでした。どの要素を処理すべきかを人が指定できることが、スクリプトだけでは解決できなかったケースを修正できる理由です。

拡張機能が通信するのは、あなたのMatomoインスタンスだけです。APIトークンは chrome.storage.local に保存されており、訪問したページとは隔離されています。テレメトリも使用状況のトラッキングもありません。コードはGitHubにあります。IssueもPull Requestも歓迎です。

公開した理由

Official Matomo Partnerエージェンシーとして、壊れたヒートマップはほぼすべてのクライアント案件で遭遇する問題でした。イベントは正しくトラッキングできているのに、スクリーンショットが使い物にならない。それがステークホルダーが実際に目にする部分です。

Matomoにはエージェンシーとして多くのものをもらっています。私たちはこの拡張機能をクライアント業務で毎日使っており、サイトで見つけたエッジケースの改善を続けています。未解決のヒートマップ問題に遭遇したら、ぜひGitHub Issueを立ててください。拡張機能に修正を加えられるか確認します。

今後の開発について

Matomo Heatmap Helperは、より大きなプロジェクトから生まれました。Martezは、Matomoを Meta Ads・Google Adsと接続することで、ROAS、CLV、マルチタッチアトリビューションを別のスプレッドシートではなくWebアナリティクスの隣に置けるようにします。現在はプライベートベータ中です。興味があれば、ウェイトリストに登録できます

いずれにせよ、ヒートマップ拡張機能はそれ単体のプロダクトであり、これからもそうあり続けます。必要だったから作りました。

Related Articles

Matomoヒートマップの壊れたスクリーンショットにどう対処しているか - Martez Blog