platform.jsでbrowser情報を取得する

platform.js
https://github.com/bestiejs/platform.js

作った方
John-David Dalton
JavaScript tinkerer, bug fixer, & benchmark runner • Creator of Lodash • Former Chakra Perf PM • Current Web Platform DX PM @Microsoft

出たー、@Microsoft!
またかよ、このパターン。。。

それはさておき、git cloneします。

[vagrant@localhost cookie]$ git clone https://github.com/bestiejs/platform.js.git
Cloning into 'platform.js'...
remote: Counting objects: 2138, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2138 (delta 2), reused 1 (delta 1), pack-reused 2135
Receiving objects: 100% (2138/2138), 3.69 MiB | 880.00 KiB/s, done.
Resolving deltas: 100% (1276/1276), done.
Checking connectivity... done.

入りました。

早速使ってみます。

<script src="platformjs/platform.js"></script>
<script type="text/javascript">
    document.write(platform.name + "<br>");
    document.write(platform.version + "<br>");
</script>

これこれ、求めてたの!

IEで見てみると、

素晴らしい!

ついでに、platform.jsの中身もざっと見てみます。このへんで、labelingしてます。

/* Detectable browser names (order is important). */
    var name = getName([
      'Adobe AIR',
      'Arora',
      'Avant Browser',
      'Breach',
      'Camino',
      'Electron',
      'Epiphany',
      'Fennec',
      'Flock',
      'Galeon',
      'GreenBrowser',
      'iCab',
      'Iceweasel',
      'K-Meleon',
      'Konqueror',
      'Lunascape',
      'Maxthon',
      { 'label': 'Microsoft Edge', 'pattern': 'Edge' },
      'Midori',
      'Nook Browser',
      'PaleMoon',
      'PhantomJS',
      'Raven',
      'Rekonq',
      'RockMelt',
      { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
      'SeaMonkey',
      { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
      'Sleipnir',
      'SlimBrowser',
      { 'label': 'SRWare Iron', 'pattern': 'Iron' },
      'Sunrise',
      'Swiftfox',
      'Waterfox',
      'WebPositive',
      'Opera Mini',
      { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
      'Opera',
      { 'label': 'Opera', 'pattern': 'OPR' },
      'Chrome',
      { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
      { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
      { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
      { 'label': 'IE', 'pattern': 'IEMobile' },
      { 'label': 'IE', 'pattern': 'MSIE' },
      'Safari'
    ]);

line79-81に以下のように書かれています。
// Platform tokens are defined at:
// http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
// http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx

これまた凄いな、ホントに。
http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx

jsでbrowser情報を取得する

<script type="text/javascript">
    document.write(navigator.appCodeName + "<br>");
    document.write(navigator.appName + "<br>");
    document.write(navigator.appVersion + "<br>");
    document.write(navigator.platform + "<br>");
    document.write(navigator.userAgent + "<br>");
</script>

chromeで見てるから、chromeと出力させたいんだが、何故mozilla、Netscapeなんだ????
仕組みが分からん。

javascriptでunixtimeを取得

ga.jsだと、new Date()は9か所で書かれてます。大体、new Date()と.getTime()が続けて書かれています。

+(new Date((new Date).getTime()+f)).toGMTString()+"; ")

a=Math.min(a,1E3*Be+a-(new Date).getTime());

this.set(ab,Math.round((new Date).getTime()/1E3));
this.set(y,Math.round((new Date).getTime()/1E3));
if("event"===a.get(sc)){var b=(new Date).getTime(),c=a.b(dc,0),d=a.b(Zb,0);

1E3 とは、10^3 つまり1000のようです。

ga.jsの真似をして1E3で書いてみます。

var date = Math.floor((new Date()).getTime()/1E3);
document.write(date);

おお、少しプログラミングが上達した錯覚を起こしますね。んな訳ない、桑原桑原。

javascriptでランダムな英数字10桁と数字10桁

console.time('timer1');
var char = "abcdefghijklmnopqrstuvwxyz123456789"
var id = "";
for(var i=0; i<10; i++){
	id += char[Math.floor(Math.random()*35)];
}
document.write(id);
console.timeEnd('timer1');

0.24609375ms
timer1: 0.411865234375ms ※2回目
timer1: 0.324951171875ms ※3回目

min:1000000000 ~ max 9999999999 の10桁の数字の場合

var id = Math.floor(Math.random() * 9000000000)+ 1000000000;
document.write(id);

timer1: 0.329833984375ms
timer1: 0.248779296875ms ※2回目
timer1: 0.24462890625ms ※3回目

感覚的に、1回の演算処理に較べて10回のforループを回す場合、レジストリの演算処理が10倍に増えるので、処理時間も約10倍位になるかと思いきや、計算してみるとforループでも処理時間はほとんど変わらない(2倍以下)ですね。multiplyとplusのCPUの処理はそんなに時間がかからない、ということなんでしょうか。よくわかりませんね。

gaがデータを送信しているように見えるdoubleclick.netとは?

doubleclick.net 
アクセスすると、doubleclickbygoogle にリダイレクトされます。。よくわからないですね。トラッキングのデータがすべて入ってくるので、広告関係をやっているのでしょうか?サイトを見ると、adコンテンツばかりです。
googleの検索アルゴリズムと、double clickが無関係(な訳ないか)なのか、どう連携しているのかも気になるところですが、運営がgoogleになっている。。
https://www.doubleclickbygoogle.com/

再び、ga.jsですが、どうやってデータを送っているのか、よくわかりません。この変だと思うのですが。。。

return"https:"==J.location.protocol||M.G?"https://ssl.google-analytics.com":"http://www.google-analytics.com"},
														Ce=function(a){
															this.name="len";this.message=a+"-8192"},
															De=function(a){
																this.name="ff2post";
																this.message=a+"-2036"},Sa=function(a,b,c,d){b=b||Fa;if(d||2036>=a.length)gf(a,b,c);
																	else if(8192>=a.length){
																		if(0<=W.navigator.userAgent.indexOf("Firefox")&&![].reduce)throw new De(a.length);

cookieの読み込み

document.cookieでcookieを全て取得します。

console.log(GetCookie('key1'));
function GetCookie(name){
	var result = null;

	var cookieName = name + '=';
	var allcookies = document.cookie;

	var position = allcookies.indexOf(cookieName);
	if(position != -1){
		var startIndex = position + cookieName.length;
		var endIndex = allcookies.indexOf(';', startIndex);
		if(endIndex == -1){
			endIndex == allcookies.length;
		}

		result = decodeURIComponent(allcookies.substring(startIndex, endIndex));
	}
	return result;
}

indexOfは全文検索。allcookieの中で、key3=のポジションを取得
indexOf(‘hoge’, n) は、nの位置から、hogeを全文検索
つまり、indexOf(‘;’, 308)は、308以降の次の’;’を検索
allcookie.substring()で、valueを切り抜いています。

console.log(document.cookie);
console.log(document.cookie.indexOf('key3=')); //position
console.log(308); // start index 
console.log(document.cookie.indexOf(';', 308)); // end index 311
console.log(document.cookie.substring(308, 311));

アフィリエイトタグとコンバージョンタグの仕組みについて

例えば、VCで広告を作成すると、以下のようなタグは発行される
sidは個人のidで固定, pidは広告の種類によって異なるので、おそらく広告ごとのid?
リンク先がurlでパラメーターとして送られているので、getで取得してsid, pidを保存、setCookieして、設定されたURLリダイレクトさせて、コンバージョンページに行ったら、jsで処理しているのか??

<script language="javascript" src="//ad.jp.ap.valuecommerce.com/servlet/jsbanner?sid=xxxxxxx&pid=yyyyyyyyy"></script><noscript><a href="//ck.jp.ap.valuecommerce.com/servlet/referral?sid=xxxxxxx&pid=yyyyyyyyy" target="_blank" rel="nofollow"><img src="//ad.jp.ap.valuecommerce.com/servlet/gifbanner??sid=xxxxxxx&pid=yyyyyyyyy" border="0"></a></noscript>

gaタグの挙動を理解する

最初gaタグは以下のような記述になっているかと思います。

<script type="text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-xxxxx-x']);
    _gaq.push(['_trackPageview']);
    (function() {

        var ga = document.createElement('script');
        ga.type = 'text/javascript';
        ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(ga, s);
    })();
</script>

ga.jsのダミーとして同じディレクトリにtest.jsを作ります。
test.js

console.log(obj[0]);

test.php
objの配列にidを入れて、test.phpからtest.jsを呼び込みます。

<script type="text/javascript">
    var obj = obj || [];
    obj.push('id:1');
    (function() {
        var sa = document.createElement('script');
        sa.type = 'text/javascript';
        sa.async = true;
        sa.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://') + '192.168.33.10:8000/test.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(sa, s);
    })();
</script>

配列のid:1がtest.jsに渡されて、console.logが実行されます。

test.jsの中身を以下に書き換えると

console.log(obj[0]);
console.log(location.pathname);

test.phpのlocation.pathnameが表示されます。

つまり、setAccountとtrackPageviewを配列としてga.jsに渡して、対象ページのユーザー情報、挙動やcookieをga.jsでcollectしているということですね。
  _gaq.push([‘_setAccount’, ‘UA-xxxxxx-x’]);
_gaq.push([‘_trackPageview’]);

あれ、もしかして、アフィリエイトのコンバージョンタグも同じ仕組み?? マジ?

Google Analyticsでip情報を取得する方法

Google Analytics -> 管理 -> プロパティ -> カスタム定義 -> カスタムディメンション をクリック
「+新しいカスタムディメンション」を押下

カスタム ディメンションを追加 で名前を追加
JavaScript(ユニバーサルアナリティクスのプロパティのみで有効)から、
ga(‘set’, ‘dimension1’, dimensionValue); をコピー

GA JSにdimension1 とphpのREMOTE_ADDRの情報を送る

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UAxxxxxx-xx', 'auto');
  ga('set', 'dimension1', <?php echo $_SERVER&#91;‘REMOTE_ADDR’&#93;; ?>);
  ga('send', 'pageview');

</script>

あとは、セカンダリディメンション・カスタムディメンションで指定した名前を見れば、ipアドレスを閲覧できますね。

ga.jsでは、タグから送られてきたdimension1とipアドレスを配列に入れて、processingしてgaにレポーティングいるだけですな。
なるほど!ga.jsはまだ途上だが、仕組み自体は少しづつ分かってきた!

javascriptでユーザー情報を取得

<script type="text/javascript">
document.write("HOST : " + location.host + "<br>");
document.write("HOSTNAME : " + location.hostname + "<br>");
document.write("PORT : " + location.port + "<br>");
document.write("REQUEST : " + location.pathname + "<br>");
document.write("CODE : " + navigator.appCodeName + "<br>");
document.write("BROWSER : " + navigator.appName + "<br>");
document.write("VERSION : " + navigator.appVersion + "<br>");
document.write("LANG : " + navigator.language + "<br>");
document.write("PLATFORM : " + navigator.platform + "<br>");
document.write("USERAGENT : " + navigator.userAgent + "<br>");
document.write("REFERER : " + document.referrer + "<br>");
document.write("DOMAIN : " + document.domain + "<br>");
document.write("SCREEN.W : " + screen.width + "<br>");
document.write("SCREEN.H : " + screen.height + "<br>");
document.write("SCREEN.COL : " + screen.colorDepth + "Bit" + "<br>");
</script>

ipアドレスがありませんね。
ga.jsでipに関する記述を見てみると、
line10: Xa=Va(“anonymizeIp”)
くらいしかみつけられません。

Google analyticsのユーザー エクスプローラはipアドレスではなく、ユーザー固有の数字のようです。