先日以下の記事を書きました。
GTM(Google Tag Manager) で ユーザのカテゴリごとのバナー配信、メッセージ配信 を行う | Monotalk

記事を書いた後に、ログインユーザであればユーザの情報は取得できるが、会員情報を持たない公開サイトだとユーザの属性情報は取得できないことに気づいて、一般的にどうやるのか調べていたら、パブリック DMP 使うとこのケースでもいろいろできることがわかりました。

ただ、無料で使えるパブリック DMP はなく、有料のパブリック DMPを使うお金もありませんので、JavaScriptのみでどこまでユーザの属性情報が取得できるか考えてみました。 考えたことを備忘として記載します。

[TOC]


前提

以下、前提条件があった上での考え事になります。

  • Google Analytics は使っている

  • ユーザの属性はリアルタイムで判定したい

  • Server 側で取得できる情報は、考慮しない1


参考

以下、記事作成中に参考にした文書リンクです。

Google Analytics で ユーザ属性を取得する

JavaScript でクライアント情報を取得する

fingerprint2


Google Analytics で 取得できる情報

参考リンクに情報がありますが、広告レポート機能有効にすることで、Google の<wbr> パブリックDMP情報が取得できるようになります。ただこれは、リアルタイムでそのユーザ属性が何かの取得はできないようです。2

現状は、サイトを訪れた人がどんな人達なのかを確認するための機能になります。
事前に分析しておいて、施作を立てて実施、効果を確認する 使い方をするものかと思います。


JavaScript で取得できる情報

JavaScritpt で取得できるユーザ属性の判断に使えそうなものがあるか調べてみました。
jackspirou/clientjs: Device information and digital fingerprinting written in pure JavaScript.いう Javascritpt で取得できるものは一通り取得できそうなLibrary があったので、その API ベースで使えるかもしれない情報をピックアップしていきます。
動作確認は、"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"実施しています。

clientjs で 取得できる情報

ユーザ属性の判断に、使えるかなと思った情報を記載します。

  • Browser の Version 情報

    • 取得コード
      var client = new ClientJS();
      client.getBrowser();
      client.getBrowserMajorVersion();;
      
    • OUTPUT
      "Chrome"
      "62"
      
  • OS 情報の取得

    • 取得コード

      var client = new ClientJS();
      client.getOS();
      client.getOSVersion();
      

    • OUTPUT

      "Mac OS"
      "10.12.6"
      

  • 言語情報

    • 取得コード

      var client = new ClientJS();
      client.getLanguage();
      

    • OUTPUT

        "ja"
      

  • タイムゾーン と 時刻

    • 取得コード

      var client = new ClientJS();
      client.getTimeZone();
      new Date();
      

    • OUTPUT

      "JST"
      Sat Dec 09 2017 13:14:41 GMT+0900 (JST)
      

  • Window サイズ等の情報を取得する

    • 取得コード

      client.getScreenPrint();
      

    • OUTPUT

      "Current Resolution: 1440x900, Available Resolution: 1440x795, Color Depth: 24, Device XDPI: undefined, Device YDPI: undefined"
      

  • Font 情報を取得する

    • 取得コード

      client.getFont();   
      

    • OUTPUT

      "Arial Black, Arial, Bauhaus 93, Chalkduster, Comic Sans MS, Courier New, Georgia, GungSeo, Hiragino Sans GB, Impact, Menlo, Microsoft Sans Serif, Papyrus, Plantagenet Cherokee, Symbol, Tahoma, Times New Roman, Trebuchet MS, Verdana, Webdings, Wingdings"
      

clientjs では取得できないが、JavaScript で取得できる情報


fingerprint2

ブラウザ・フィンガープリントという技術があり、完全一致ではないですがブラウザの情報から一意のキーを生成できます。 ドメインの違うサイトでも同一のキーが取得できるので、ドメインを跨いだユーザーのトラッキングに使用したり、端末情報を含めた認証処理などに使用できます。
Valve/fingerprintjs2: Modern & flexible browser fingerprinting libraryいうライブラリで、JavaScript で取得できる情報でブラウザ・フィンガープリントを生成できるのですが、フィンガープリントの元になっている情報も取得できます。

CDN配信されているので、以下スクリプトタグをHTMLに追加すると使用できます。

<script src="https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/2.1.0/fingerprint2.js" integrity="sha256-RBGR32F9JdIr/VzBmTp/iQ73Ibl6woprrQ4xj5Rr+mM=" crossorigin="anonymous"></script>    

JavaScriptからタグを追加する場合は以下のスクリプトを実行します。

(function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/2.1.0/fingerprint2.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
以下、スクリプトでブラウザの情報が取得できます。
{excludes: {userAgent: true}} userAgent の情報は除外しています。
var options = {excludes: {userAgent: true}};
Fingerprint2.get(options, function(result) {
  var jsonString = JSON.stringify(result)
  console.log(jsonString);
});
私が使用しているMAC の Chrome の情報を取得してみました。
Canvas の フィンガープリントの情報と、WebGL の フィンガープリントの情報は長すぎるので省略しています。
{excludes: {userAgent: true}} userAgent の情報は除外しているため、JSON文字列として取得できません。
[{
    "key": "webdriver",
    "value": "not available"
}, {
    "key": "language",
    "value": "ja"
}, {
    "key": "colorDepth",
    "value": 24
}, {
    "key": "deviceMemory",
    "value": "not available"
}, {
    "key": "pixelRatio",
    "value": 2
}, {
    "key": "hardwareConcurrency",
    "value": 12
}, {
    "key": "screenResolution",
    "value": [1680, 1050]
}, {
    "key": "availableScreenResolution",
    "value": [947, 1680]
}, {
    "key": "timezoneOffset",
    "value": -540
}, {
    "key": "timezone",
    "value": "Asia/Tokyo"
}, {
    "key": "sessionStorage",
    "value": true
}, {
    "key": "localStorage",
    "value": true
}, {
    "key": "indexedDb",
    "value": true
}, {
    "key": "addBehavior",
    "value": false
}, {
    "key": "openDatabase",
    "value": true
}, {
    "key": "cpuClass",
    "value": "not available"
}, {
    "key": "platform",
    "value": "MacIntel"
}, {
    "key": "doNotTrack",
    "value": "not available"
}, {
    "key": "plugins",
    "value": [
        ["Chrome PDF Plugin", "Portable Document Format", [
            ["application/x-google-chrome-pdf", "pdf"]
        ]],
        ["Chrome PDF Viewer", "", [
            ["application/pdf", "pdf"]
        ]],
        ["Native Client", "", [
            ["application/x-nacl", ""],
            ["application/x-pnacl", ""]
        ]]
    ]
}, {
    "key": "canvas",
    "value": ["canvas winding:yes", "canvas fp:data:image/png;base64,........."]
}, {
    "key": "webgl",
    "value": ["data:image/png;base64,iVBORw0KGgoAA........", "extensions:ANGLE_instanced_arrays;EXT_blend_minmax;EXT_color_buffer_half_float;EXT_disjoint_timer_query;EXT_float_blend;EXT_frag_depth;EXT_shader_texture_lod;EXT_texture_filter_anisotropic;WEBKIT_EXT_texture_filter_anisotropic;EXT_sRGB;OES_element_index_uint;OES_standard_derivatives;OES_texture_float;OES_texture_float_linear;OES_texture_half_float;OES_texture_half_float_linear;OES_vertex_array_object;WEBGL_color_buffer_float;WEBGL_compressed_texture_s3tc;WEBKIT_WEBGL_compressed_texture_s3tc;WEBGL_compressed_texture_s3tc_srgb;WEBGL_debug_renderer_info;WEBGL_debug_shaders;WEBGL_depth_texture;WEBKIT_WEBGL_depth_texture;WEBGL_draw_buffers;WEBGL_lose_context;WEBKIT_WEBGL_lose_context;WEBGL_multi_draw;WEBGL_multi_draw_instanced;WEBGL_video_texture", "webgl aliased line width range:[1, 1]", "webgl aliased point size range:[1, 8191]", "webgl alpha bits:8", "webgl antialiasing:yes", "webgl blue bits:8", "webgl depth bits:24", "webgl green bits:8", "webgl max anisotropy:16", "webgl max combined texture image units:80", "webgl max cube map texture size:16384", "webgl max fragment uniform vectors:1024", "webgl max render buffer size:16384", "webgl max texture image units:16", "webgl max texture size:16384", "webgl max varying vectors:32", "webgl max vertex attribs:16", "webgl max vertex texture image units:16", "webgl max vertex uniform vectors:1024", "webgl max viewport dims:[16384, 16384]", "webgl red bits:8", "webgl renderer:WebKit WebGL", "webgl shading language version:WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)", "webgl stencil bits:0", "webgl vendor:WebKit", "webgl version:WebGL 1.0 (OpenGL ES 2.0 Chromium)", "webgl unmasked vendor:ATI Technologies Inc.", "webgl unmasked renderer:AMD Radeon Pro 555X OpenGL Engine", "webgl vertex shader high float precision:23", "webgl vertex shader high float precision rangeMin:127", "webgl vertex shader high float precision rangeMax:127", "webgl vertex shader medium float precision:23", "webgl vertex shader medium float precision rangeMin:127", "webgl vertex shader medium float precision rangeMax:127", "webgl vertex shader low float precision:23", "webgl vertex shader low float precision rangeMin:127", "webgl vertex shader low float precision rangeMax:127", "webgl fragment shader high float precision:23", "webgl fragment shader high float precision rangeMin:127", "webgl fragment shader high float precision rangeMax:127", "webgl fragment shader medium float precision:23", "webgl fragment shader medium float precision rangeMin:127", "webgl fragment shader medium float precision rangeMax:127", "webgl fragment shader low float precision:23", "webgl fragment shader low float precision rangeMin:127", "webgl fragment shader low float precision rangeMax:127", "webgl vertex shader high int precision:0", "webgl vertex shader high int precision rangeMin:31", "webgl vertex shader high int precision rangeMax:30", "webgl vertex shader medium int precision:0", "webgl vertex shader medium int precision rangeMin:31", "webgl vertex shader medium int precision rangeMax:30", "webgl vertex shader low int precision:0", "webgl vertex shader low int precision rangeMin:31", "webgl vertex shader low int precision rangeMax:30", "webgl fragment shader high int precision:0", "webgl fragment shader high int precision rangeMin:31", "webgl fragment shader high int precision rangeMax:30", "webgl fragment shader medium int precision:0", "webgl fragment shader medium int precision rangeMin:31", "webgl fragment shader medium int precision rangeMax:30", "webgl fragment shader low int precision:0", "webgl fragment shader low int precision rangeMin:31", "webgl fragment shader low int precision rangeMax:30"]
}, {
    "key": "webglVendorAndRenderer",
    "value": "ATI Technologies Inc.~AMD Radeon Pro 555X OpenGL Engine"
}, {
    "key": "adBlock",
    "value": false
}, {
    "key": "hasLiedLanguages",
    "value": false
}, {
    "key": "hasLiedResolution",
    "value": false
}, {
    "key": "hasLiedOs",
    "value": false
}, {
    "key": "hasLiedBrowser",
    "value": false
}, {
    "key": "touchSupport",
    "value": [0, false, false]
}, {
    "key": "fonts",
    "value": ["Andale Mono", "Arial", "Arial Black", "Arial Narrow", "Arial Rounded MT Bold", "Arial Unicode MS", "Comic Sans MS", "Courier", "Courier New", "Geneva", "Georgia", "Helvetica", "Helvetica Neue", "Impact", "LUCIDA GRANDE", "Microsoft Sans Serif", "Monaco", "Palatino", "Tahoma", "Times", "Times New Roman", "Trebuchet MS", "Verdana", "Wingdings", "Wingdings 2", "Wingdings 3", "American Typewriter", "Apple Chancery", "Apple SD Gothic Neo", "AVENIR", "Ayuthaya", "Bangla Sangam MN", "Baskerville", "Big Caslon", "Bodoni 72", "Bodoni 72 Oldstyle", "Bodoni 72 Smallcaps", "Bradley Hand", "Brush Script MT", "Chalkboard", "Chalkboard SE", "Chalkduster", "Cochin", "Copperplate", "Didot", "Euphemia UCAS", "Futura", "Geeza Pro", "Gill Sans", "Gujarati Sangam MN", "Gurmukhi MN", "Heiti SC", "Heiti TC", "Hiragino Kaku Gothic ProN", "Hiragino Mincho ProN", "Hoefler Text", "Kailasa", "Kannada Sangam MN", "Krungthep", "Malayalam Sangam MN", "Marion", "Marker Felt", "Nadeem", "Noteworthy", "OPTIMA", "Oriya Sangam MN", "OSAKA", "Papyrus", "Plantagenet Cherokee", "Rockwell", "Savoye LET", "Sinhala Sangam MN", "Skia", "Snell Roundhand", "Tamil Sangam MN", "Telugu Sangam MN", "Thonburi", "Zapfino"]
}, {
    "key": "fontsFlash",
    "value": "swf object not loaded"
}, {
    "key": "audio",
    "value": "124.04345808873768"
}, {
    "key": "enumerateDevices",
    "value": "not available"
}]
フィンガープリントを取得する場合は、以下のように実装します。
murmur値がフィンガープリントになります。
var options = {excludes: {userAgent: true}};
Fingerprint2.get(options, function (components) {
    var values = components.map(function (component) { return component.value });
    var murmur = Fingerprint2.x64hash128(values.join(''), 31);
    console.log(murmur);
})

変数名のmurmur意味がよくわからなかったのですが、MurmurHash というハッシュアルゴリズムがあるようで、以下の日本語記事が参考になりました。
MurmurHashとは何か - kenju’s blog

私が使用しているMAC の Chromeでは以下のようなフィンガープリントが取得できました。

7aef723621360003b5065446fed3df90


JavaScript で取得できる情報でどんなことがわかるのか

IT への興味

OS Version ブラウザの Version 情報で、最近発売されたものかそうではないかはわかります。
アクセス時間帯が日中だと、仕事で使用している端末が古い可能性があり、夜間や休日の場合、自宅の端末が古い可能性があります。
端末が古い > IT リテラシの高い/低い は言い過ぎですが、それほど IT 関連に興味がない人の可能性が高いとか考えました。
必要な項目は以下の通りです。

  • OS 情報

  • Browser の Version 情報

  • タイムゾーン と 時刻

多言語が話せる人か

多言語化対応されているサイトだと、意味のないとは思いますが、言語設定が en で、日本語のサイトを閲覧している。その逆だったりする場合、多言語が話せる人である可能性が高そうです。
必要な項目は言語コードのみです。

フォントに拘る職業か、興味があるか

インストールしているフォントを取得することができます。デフォルトフォントとは異なる設定の人は、フォントに興味がある人、フォントのインストールが必要な職業である可能性が高そうです。
必要な項目は Font のみです。

位置情報

位置情報で地域がわかります。どこからアクセスしている人なのかを知ることができます。
必要な項目は 位置情報 で、経度、緯度から、地域を導出する API 等を叩く必要があります。


まとめ

JavaScript で 取得できる情報で ユーザの属性情報が取得できるか考えてみました。
以下まとめます。

  • たいした情報は取得できない。

  • 無理矢理考えると、考えついたが、何か極端で断片的な情報な気がする。

  • お金を出せるなら、パブリック DMP を使ったほうがいい。

  • JavaScript のみに拘らなければ、時間差はあるが、Google Analytics のデータは使えるのでもう少し踏み込んだ属性情報を使えるかもしれない。

  • ブラウザ・フィンガープリント という技術がある。ブラウザ・フィンガープリント単体では単なる暗号キーなのだが、ドメインを超えて同じキーが取得できるので複数サイトを横断した行動ログを蓄積できる。

以上です。


  1. IP アドレス等です。 

  2. リアルタイム データ: get  |  アナリティクス Real Time Reporting API  |  Google Developersいう API がありますが、これはユーザ属性が取得できなそうです。 

コメント