JSによる様々なSafari ITP影響ブラウザからのアクセス判定の方法

ITP対応のため、各アドテクノロジーツール提供元企業がJavaScriptを使ってどのようにSafariブラウザからのアクセスを判定しているのか個人的に気になったのでまとめました。参考までにどうぞ。

# SafariブラウザのUser Agent例

|デバイス| OS | User Agent |
|:-:|:-:|:--|
|iPhone|Safari 13 on iOS 13|`Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1`|
|iPad|Safari 12.1 on iOS 12.2|`Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1`|
|mac|Safari 12 on macOS (High Sierra)|`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15`|

その他の例は以下記事を参照

- [各ブラウザのUserAgent一覧 - Qiita](https://qiita.com/kapiecii/items/093ffd6f0b09ad775250)
- [iOS 13 / iPadOS 13 Webブラウザのユーザーエージェント (Safari, Google Chrome, LINE, Twitter など) - Qiita](https://qiita.com/niwasawa/items/df30ffddf2e709b2ca43)
- [Safari User Agents - WhatIsMyBrowser.com](https://developers.whatismybrowser.com/useragents/explore/software_name/safari/)

# 各アドテクツール内での判定
## Yahoo! JAPAN
[サイトジェネラルタグ](https://ads-help.yahoo.co.jp/yahooads/ss/articledetail?lan=ja&aid=47048)内にてシンプルな正規表現によりUserAgentの文字列を見てSafariかどうか推定。

UserAgentに`iPhone`か`iPad`か`Macintosh`かいずれかの文字列を含んでおり、
かつ、それ以降に、`Version/`を含み、その直後に11～19の数字が続き、
かつ、それ以降に`Safari/`という文字列を確認できた場合、ITP影響下にあるSafariブラウザであると推定。
https://s.yimg.jp/images/listing/tool/cv/ytag.js

```js:
isSafari: function(e) {
  return new RegExp("(iPhone|iPad|Macintosh).*Version/1[1-9].*Safari/").test(e)
}
```
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/d0bc40c7-fe4c-59c1-469f-abac853c13d1.png)


## Google Analytics
UserAgentに`"Cheome"`,`"crios"`(iOS版Chrome)の何れの文字列も含まない。
かつ、`"Safari/"`か`"Safari,"`の文字列を含むとき、Safariブラウザからのアクセスと推定。バージョン11以上でITP影響ブラウザと判定。
https://www.google-analytics.com/analytics.js

```js:
var oc,
  Id = /^.*Version\/?(\d+)[^\d].*$/i,
  ne = function() {
    if (void 0 !== O.__ga4__) return O.__ga4__;
    if (void 0 === oc) {
      var a = O.navigator.userAgent;
      if (a) {
        var b = a;
        try {
          b = decodeURIComponent(a)
        } catch (c) {}
        if (a = !(0 <= b.indexOf("Chrome")) && !(0 <= b.indexOf("CriOS")) && (0 <= b.indexOf("Safari/") || 0 <= b.indexOf("Safari,")))
          b = Id.exec(b), a = 11 <= (b ? Number(b[1]) : -1);
        oc = a
      } else oc = !1
    }
    return oc
  };
```


## Criteo
以下の正規表現とマッチするときSafariブラウザと推定。更にバージョン11以上でITP影響ブラウザと判定。
`/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[^ ]+ \(KHTML, like Gecko\) Version\/([^ ]+)( Mobile\/[^ ]+)? Safari\/[^ ]+$/i`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/88ede009-e3de-18de-9103-cc5aec52126e.png)
https://static.criteo.net/js/ld/ld.js

## Logicad
UserAgentを小文字化した上で、`"iphone"`,`"ipod"`,`"ipad"`の何れかの文字列を含んでいることを確認し、
その上で、`"crios"`(iOS版Chrome),`"opera"`,`"opios"`(iOS版Opera)などの文字列を含んでいないことを確認できたとき
Safariブラウザからのアクセスと推定。Macの存在は無視している？
https://cd.ladsp.com/script-sf/v5/sf.min.js

```js:
smnLogicadSfManager.isIosSafari = function () {
    var u = window.navigator.userAgent.toLowerCase(),
        c = function (s) {
            return -1 != u.indexOf(s)
        },
        d = function (s) {
            return !(function (s) {
                return -1 != u.indexOf(s)
            })();
        };
    return (c("iphone") || c("ipod") || c("ipad")) &&
        d("crios") && d("opera") && d("opios") && d("fxios") &&
        d("google") && d("yahoo") && d("y!j") && d("bing") &&
        d("bot") && d("crawl") && d("spider")
};
```

## MicroAd BLADE
UserAgentに`Safari`を含んでおり、かつ`Version/`の後に何かしらの1文字があり、その後に数字が続いた場合、
かつ、`Version/`の後に続く数字が11以上ならITP影響ブラウザと判定。（「何かしらの1文字」の判定は何のために用意してるんだろう。。）
https://d-cache.microad.jp/js/blade_track_jp.js

```js:
function isItpBrowser() {
  if (navigator.userAgent.match(/Safari/) && navigator.userAgent.match(/Version\/(.\d+)/)) {
    return navigator.userAgent.match(/Version\/(.\d+)/)[1] >= 11;
  } else {
    return false;
  }
}
```

## AccessTrade
UserAgentを小文字化した上で`"macintosh"`,`"iphone"`,`"ipad"`の何れかの文字列を含んでいる。
かつ、`"safari"`,`"version"`の文字列を両方含み、`"chrome"`,`"edge"`の何れの文字列7含まないとき、Safariと推定。
更に、UserAgent中の`os `あるいは`mac os x 10_`の直後の2桁の数字を見ることでITP影響ブラウザと判定。
https://h.accesstrade.net/js/nct/lp.min.js

```js:
t.hasITP = function(e) {
  var t = e.toLowerCase();
  if ((-1 !== t.indexOf("macintosh") || -1 !== t.indexOf("iphone") || -1 !== t.indexOf("ipad")) && -1 !== t.indexOf("safari") && -1 !== t.indexOf("version") && -1 === t.indexOf("chrome") && -1 === t.indexOf("edge")) {
    var n = t.match(/os (\d{2})_/);
    if (null !== n && +n[1] >= 11) return !0;
    var r = t.match(/mac os x 10_(\d{2})/);
    if (null !== r && +r[1] >= 13) return !0
  }
  return !1
}
```

部分部分を切り取って見ているのでもっとよく読んだら更にしっかりした判定をしているかも。各社個性があって面白いです。
他にも見つけたら随時追加予定。

# その他参考になる記事
- [UserAgentからOS/ブラウザなどの調べかたのまとめ - Qiita](https://qiita.com/nightyknite/items/b2590a69f2e0135756dc)
- [ブラウザのUser-Agentが滅茶苦茶になってしまった理由 - Qiita](https://qiita.com/natsuozawa/items/02313e86ec5da90463d1)
- [window.navigator.userAgent - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/NavigatorID/userAgent)
- [Firefox ユーザーエージェント文字列リファレンス - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/User-Agent/Firefox)