GoogleAnalyticsとBeacon API

:::note warn
この記事はGoogle Analytics 4ではなく、Universal Analyticsを対象としています。
:::

## Beacon API非対応端末の割合を知りたい
analytics.jsの[フィールドリファレンス](analytics.js のフィールド リファレンス)に記載されているように、トランスポートをbeaconで指定した場合はログ送信にBeacon APIが利用され、ブラウザがAPIに対応していない場合はフォールバックされます。

> 「beacon」を指定したときに、ユーザーのブラウザで「navigator.sendBeacon」メソッドが使用できない場合は、ヒットサイズに応じて「image」または「xhr」にフォールバックされます。

ここでは実際にどの程度の端末がbeaconに対応していないのか、GAイベントを利用して調査してみます。

## 調査方法
GTM or Optimizeのパーソナライズで以下のようなJavaScriptをセットします。

```javascript

if(navigator.sendBeacon){
    ga("send", "event", "category", "beacon_status", "true")
} else {
    ga("send", "event", "category", "beacon_status", "false")
    ga("send", "event", "category", "beacon_status", "can_fallback", {"transport":"beacon"})
}
```

※analytics.jsをGTMで配信している場合には[トラッカー名](https://qiita.com/satoru-ka/items/35df5b30760fa09c4bf3)を指定してください。

APIがあればtrueで、なければfalseでセットされ、さらに念のためtransportオプションを指定してフォールバックして送信されるかをチェックします。
## 抽出

BigQueryから抽出してみます。

```sql
WITH
  raw_data AS (
  SELECT DISTINCT
    fullVisitorId,
    hits.eventInfo.eventLabel AS label
  FROM
    `project_name.dataset_name.ga_sessions_YYYYMMDD`,
    UNNEST(hits) AS hits
  WHERE
    hits.type = "EVENT"
    AND hits.eventInfo.eventAction = "beacon_status" )
SELECT
  label,
  COUNT(label) AS count
FROM
  raw_data
GROUP BY
  label
```

## 結果

22万人のうち1000人近くが非対応 という結果で、非対応においてはほぼ同数がフォールバック送信できていました。

| 行  | label  |  count | 
|---|---|---|
| 1  | true  | 225010  |
| 2  | false  | 1053  |
| 3  |  can_fallback | 1050  | 

非対応ブラウザは全体の0.5%程度という認識でよさそうです。

## Beacon API非対応端末
GTM側で特定キャリアのUA/端末名の辞書を保持してカスタムディメンションにセットしているため、falseイベントが発生した端末を抽出してみます。

### 抽出

```sql

WITH
  raw_data AS (
  SELECT
    DISTINCT (
    SELECT
      MAX(
      IF
        (index=cuntom_dimension_index,
          value,
          NULL))
    FROM
      UNNEST(hits.customDimensions)) AS device,
    hits.eventInfo.eventLabel AS label,
    fullvisitorId,
    device.operatingSystemVersion as os_ver,
    device.operatingSystem as os
  FROM
    `project_name.dataset_name.ga_sessions_YYYYMMDD`,
    UNNEST(hits) AS hits
  WHERE
    hits.type = "EVENT"
    AND hits.eventInfo.eventAction = "beacon_status" )
SELECT
  os,
  os_ver,
  device,
  COUNT(device) AS count
FROM
  raw_data
WHERE
  label = "false"
GROUP BY
  device,os,os_ver
ORDER BY
  count DESC
LIMIT 20
```

### 結果
Android4.4.x以下、iOS11.2以下が非対応となっていて、[can I use](https://caniuse.com/beacon)と同じ結果になりました。ただ、Android5.x系も含まれていることから 厳密にはAndroid5.x以下が非対応なのかもしれません。

| 行 | os      | os_ver | device | count |
|----|---------|--------|--------|-------|
|  1 | Android | 4.4.4  | KYV32  |    75 |
|  2 | iOS     | 11.2.5 | other  |    28 |
|  3 | iOS     | 11.2.6 | other  |    24 |
|  4 | iOS     | 11.1.2 | other  |    21 |
|  5 | iOS     | 11.2.1 | other  |    20 |
|  6 | iOS     | 10.3.3 | other  |    20 |
|  7 | Android | 4.4.4  | SHV31  |    16 |
|  8 | iOS     | 11.0   | other  |    15 |
|  9 | iOS     | 10.2.1 | other  |    13 |
| 10 | iOS     | 11.0.3 | other  |    12 |
| 11 | Android | 4.4.2  | KYY23  |    12 |
| 12 | Android | 4.4.4  | SHF32  |    11 |
| 13 | Android | 4.4.4  | SHF31  |    11 |
| 14 | Android | 4.4.4  | SHF33  |    10 |
| 15 | iOS     | 10.2   | other  |    10 |
| 16 | Android | 4.4.2  | KYY24  |    10 |
| 17 | Android | 5.0.2  | HTL23  |     9 |
| 18 | iOS     | 11.2   | other  |     8 |
| 19 | iOS     | 11.2.2 | other  |     8 |
| 20 | iOS     | 11.0.2 | other  |     7 |

## ということで
非対応の割合は0.5%程度で、GA側でもフォールバックしてくれるので欠落は最小限に抑えられ、むしろこれまで欠落していたページ遷移等のログが計測できるようになるので、全体としてログは増える方向になりそうです。

ページ遷移時のログ欠落を防いだりGETリクエストでのURL文字列上限を回避するためにも、積極的にbeaconを利用していきたいですね。