先日以下の記事を書きました。
GTM(Google Tag Manager) で ユーザのカテゴリごとのバナー配信、メッセージ配信 を行う | Monotalk
記事を書いた後に、ログインユーザであればユーザの情報は取得できるが、会員情報を持たない公開サイトだとユーザの属性情報は取得できないことに気づいて、一般的にどうやるのか調べていたら、パブリック DMP 使うとこのケースでもいろいろできることがわかりました。
ただ、無料で使えるパブリック DMP はなく、有料のパブリック DMPを使うお金もありませんので、JavaScriptのみでどこまでユーザの属性情報が取得できるか考えてみました。 考えたことを備忘として記載します。
前提
以下、前提条件があった上での考え事になります。
Google Analytics は使っている
ユーザの属性はリアルタイムで判定したい
Server 側で取得できる情報は、考慮しない1
参考
以下、記事作成中に参考にした文書リンクです。
Google Analytics で ユーザ属性を取得する
JavaScript でクライアント情報を取得する
jackspirou/clientjs: Device information and digital fingerprinting written in pure JavaScript.
javascript - What information can we access from the client? - Stack Overflow
Detect my Browser :: Browser, Browser Plugin, HTML5 and CSS3 detection
JavaScript API でブラウザ情報を取得し表示してくれるオンラインツール。
fingerprint2
「FingerPrint2」に見るブラウザフィンガープリントの最新事情 - その1 - - TOKYO MARTECH BLOG
「FingerPrint2」に見るフィンガープリンティングの最新事情 - その2 - - TOKYO MARTECH BLOG
WebGL Browser Report - WebGL Fingerprinting - WebGL 2 Test - BrowserLeaks.com
Google Analytics で 取得できる情報
参考リンクに情報がありますが、広告レポート機能
を有効にすることで、Google の パブリック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 で取得できる情報
- 位置情報
Geolocation API
で 経度、緯度の情報は取得できます。「XXX
は次の許可を求めています。ユーザーの現在地の認識」が出てくるので、気にする人、気にしない人がいそうに思います。
以下の記事が参考になりました。
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); });
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 のデータは使えるのでもう少し踏み込んだ属性情報を使えるかもしれない。
ブラウザ・フィンガープリント という技術がある。ブラウザ・フィンガープリント単体では単なる暗号キーなのだが、ドメインを超えて同じキーが取得できるので複数サイトを横断した行動ログを蓄積できる。
以上です。
IP アドレス等です。 ↩
リアルタイム データ: get | アナリティクス Real Time Reporting API | Google Developers という API がありますが、これはユーザ属性が取得できなそうです。 ↩
コメント