【JavaScript】Google AnalyticsとAdSenseを遅延読み込みする

JavaScript

当サイトの読み込み速度改善の一環として、Google AnalyticsとAdSenseの読み込みを遅延読み込みに対応させてみました。その方法についてまとめてみました。

はじめに

Google AnalyticsとAdSenseのコードは、通常<head>タグ内に配置されます。このままですと、ページの読み込みの最初にこれらのJavaScriptが読み込まれ、実行されます。これがページの表示を遅らせる要因となっています。

PageSpeed Insightsでは、パフォーマンスのスコアを落とす要因となっており、できれば対策しておきたいところです。

そこで、これらのJavaScriptの読み込みと実行を特定のイベントが発生した際に行われるように変更してみました。

JavaScriptによる遅延読み込みの方法

特定のイベントが発生した場合に、JavaScriptの読み込みと実行が行われるようにするためには、addEventLister()メソッドを用います。addEventListener()では、対象となるイベントとイベントリスナとなるコールバック関数を登録し、指定したイベントが発生したら関数が呼び出されるようにします。

window.addEventListener(イベント, コールバック関数);

遅延読み込みをするためには、コールバック関数内で、<script>タグを生成し、DOMに追加します。こうすることにより、特定にイベントが発生した場合に、コールバック関数が呼び出され、その中で<script>タグが解析されJavaScriptが実行されるようになります。

以下の例では、マウスをクリックするたび<script>タグを生成する場合を示します(実際は、マウスクリックされるたびにタグが生成されては困るため、何らかの仕掛けが必要です)。

function onMouseDown() {
  const sc = document.createElement("script");
  sc.type = "text/javascript";
  sc.src = "http://~/~.js";
  document.head.appendChild(sc);
}

window.addEventListener("mousedown", onMouseDown);

これをGoogle AnalyticsのコードスニペットやAdSenseのコードスニペットに応用します。これらのスニペットには、<script>タグがあるので、この部分をJavaScriptを使ってイベント発生時に動的に生成することとします。

たとえば、Google Analyticsのコードスニペットに適用する場合、JavaScriptのコードは以下のようになります。

let lazyLoadAnalytics = false;

// XXXXXXはタグIDに置き換えてください
function onLazyLoadAnalytics() {
  if(!lazyLoadAnalytics) {
    lazyLoadAnalytics = true;
    window.removeEventListener("mousedown", onLazyLoadAnalytics);
  }

  const sc = document.createElement("script");
  sc.type = "text/javascript";
  sc.async = true;
  sc.src = "https://www.googletagmanager.com/gtag/js?id=XXXXXX";
  document.head.appendChild(sc);

  window.dataLayer = window.dataLayer || [];
  function gtag() { dataLayer.push(arguments); }
  gtag("js", new Date());
  gtag("config", "XXXXXX");
}

window.addEventListener("mousedown", onLazyLoadAnalytics);

実際のコード

実際のコードは以下となります。これを<body>タグの最下部に記載します。

登録するイベントは、スクロール"scroll"、マウス移動"mousemove"、タッチ操作の開始"touchstart"としました。

<script>
function funcLazyLoad(src, obj, func) {
  let lazyLoad = false;

  function onLazyLoad() {
    if (!lazyLoad) {
      lazyLoad = true;
      window.removeEventListener("scroll", onLazyLoad);
      window.removeEventListener("mousemove", onLazyLoad);
      window.removeEventListener("touchstart", onLazyLoad);
    }

    const sc = document.createElement("script");
    sc.type = "text/javascript";
    sc.async = true;
    sc.src = src;
    Object.assign(sc, obj);
    document.head.appendChild(sc);

    if (func) {
      func();
    }
  }

  return function () {
    window.addEventListener("scroll", onLazyLoad);
    window.addEventListener("mousemove", onLazyLoad);
    window.addEventListener("touchstart", onLazyLoad);
    window.addEventListener("load", function () {
      if (window.pageYOffset) {
        onLazyLoad();
      }
    });
  };
}

// Google Analytics(XXXXXXはタグIDに置き換えてください)
const gt = funcLazyLoad(
  "https://www.googletagmanager.com/gtag/js?id=XXXXXX",
  {}, function () {
    window.dataLayer = window.dataLayer || [];
    function gtag() { dataLayer.push(arguments); }
    gtag("js", new Date());
    gtag("config", "XXXXXX");
  },
);

// Google AdSense(XXXXXXはパブリッシャーIDに置き換えてください)
const ad = funcLazyLoad(
  "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=XXXXXX",
  { crossOrigin: "anonymous" }
);

gt();
ad();
</script>

関数funcLazyLoad()はクロージャです。

まず関数内で、遅延読み込みが実施されたかどうか判断するフラグlazyLoadを定義しています。次に、遅延読み込みのための<script>タグを生成するための関数onLazyLoad()を定義しています。この関数の中で、フラグlazyLoadを参照し、初回の関数呼び出しの時にremoveEventListener()メソッドを使ってイベントリスナを削除します。

その後、<script>タグをcreateElement()メソッドを使って生成します。追加する場所は<head>タグの中としています。src属性は、funcLazyLoad()の引数として与えます。また、Google Analyticsでは追加のコードが、AdSenseではcrossorigin属性が必要となるため、これもfuncLazyLoad()の引数として与えられるようにしました。

注意点としては、<script>タグのcrossorigin属性の設定です。HTML上ではcrossoriginとなりますが、JavaScriptのプロパティとして設定する場合、crossOriginと’O’が大文字となります。 うっかり小文字で記述してしまい、生成されたタグに反映されないことがあるので注意しましょう。

funcLazyLoad()関数の戻り値で、addEventListener()メソッドを使ってイベントリスナを登録する関数を返しています。イベントリスナとして、onLazyLoad()を与え、イベント発生時に<script>タグが生成されるようにしています。なお、外部リンクからページ途中へ飛んできた場合にも対応できるように、loadイベントが発生した場合に、ページ途中であれば即座にonLazyLoad()を実行するようにもしています。

このようにクロージャを使って記述すると、遅延読み込み部分のコードが再利用でき、シンプルになります。

まとめ

Google AnalyticsとAdSenseのコードスニペットを置き換え、遅延読み込みを実施する方法についてまとめてみました。同種のコードはいろいろなサイトで公開されていますが、クロージャを使っている例はあまりないように思います。

実際のコードに示したようにクロージャを使って記述すると、遅延読み込み部分のコードが再利用でき、シンプルに記述できます。また、Google AnalyticsやAdSenseに限らず、汎用的に使うことが可能です。

JavaScript

Posted by izadori