datepicker

  var dateFormat = 'yy-mm-dd';
  var form = document.getElementById('datepicker').value;
  $(function() {
    $("#datepicker").datepicker({
    	onClose: function(dateText, inst){
    		$('#datepicker2').datepicker('option', 'minDate', dateText);
    		$('#datepicker').val(dateText);
    	}
    });
    $("#datepicker2").datepicker({
    	onClose: function(dateText, inst){
    		$('#datepicker').datepicker('option', 'maxDate', dateText);
    		$('#datepicker2').val(dateText);
    	}
    });
  });

onClose
->DatePickerが閉じた時に実行
:function( String dateText, Object inst )

1.datepicker1が閉じるときに、datepicker2のminDateをdateTextにして、datapickerのvalをdateTextにする
2.datepicker2が閉じるときに、datepicker2のminDateをdateTextにして、datapickerのvalをdateTextにする

今日以前の日付にする

  var dateFormat = 'yy-mm-dd';
  var form = document.getElementById('datepicker').value;
  $(function() {
    $("#datepicker").datepicker({
    	dateFormat: dateFormat,
    	maxDate:0,
    	onClose: function(dateText, inst){
    		$('#datepicker2').datepicker('option', 'minDate', dateText);
    		$('#datepicker').val(dateText);
    	}
    });
    $("#datepicker2").datepicker({
    	dateFormat: dateFormat,
    	maxDate:0,
    	onClose: function(dateText, inst){
    		$('#datepicker').datepicker('option', 'maxDate', dateText);
    		$('#datepicker2').val(dateText);
    	}
    });
  });

来た!
今日以前の日付で、datapicker1のdateTextがdatapicker2のminDate, datapicker2のdateTextがdatapicker2のmaxDateになる。

datepickerを使う

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css" >
<input type="text" id="datepicker">
<script>
  $(function() {
    $("#datepicker").datepicker();
  });
</script>

このように書くと、下のフォームは動きません。

<input type="text" id="datepicker"><br>
<input type="text" id="datepicker">
<script>
  $(function() {
    $("#datepicker").datepicker();
  });
</script>

idを変えると両方動きます。

<input type="text" id="datepicker"> ~ <input type="text" id="datepicker2">
<script>
  $(function() {
    $("#datepicker").datepicker();
  });
  $(function() {
    $("#datepicker2").datepicker();
  });
</script>

今日と10日前の初期値を入れます。

<?php
$date1 = date("Y/m/d", strtotime("-10 days"));
$date2 = date("Y/m/d");

?>
<style>
input{
	width:90px;
}
</style>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css" >
<input type="text" id="datepicker" value="<?php echo $date1; ?>"> ~ <input type="text" id="datepicker2" value="<?php echo $date2; ?>">
<script>
  $(function() {
    $("#datepicker").datepicker();
  });
  $(function() {
    $("#datepicker2").datepicker();
  });
</script>

あれ、割と簡単に出来た

Y-m-dにして、date1、date2をgetで渡して、mongodbで読み取ればOKだと思います。

時間別のPVをchart.jsで表示する

全て繋げます。

<?php

// $date1 = date("Y-m-d H:i:s", strtotime("- 6 day"));
$date1 = date("Y-m-d", strtotime("-10 day"));
// $date2 = date("Y-m-d H:i:s", strtotime("- 1 day"));
$date2 = date("Y-m-d H:i:s");


$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$filter =  &#91;
	'date' => [ '$gte' => $date1, '$lte' => $date2]
];
$options = [
  'projection' => ['_id' => 0],
  'sort' => ['_id' => -1],
];
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $mng->executeQuery('app.na007', $query);

foreach ($cursor as $document) {
  // var_dump($document);
  $pv[] = $document->date;
  $cookie[] = $document->cookie;
  $session[] = $document->session;
  if(!is_null($document->referrer)){
  $avgtime[] = $document->avgtime;
  }
  if(!is_null($document->referrer)){
  $referrer[] = $document->referrer;
  }
  $visit[] = $document->visit;
  $access[] = substr($document->date, 11, 2);
}
$visit = json_encode(array_count_values($visit));
$line = array("00"=>0,"01"=>0, "02"=>0,"03"=>0,"04"=>0,"05"=>0,"06"=>0,"07"=>0,"08"=>0,"09"=>0,"10"=>0,"11"=>0,"12"=>0,"13"=>0,"14"=>0,"15"=>0,"16"=>0,"17"=>0,"18"=>0,"19"=>0,"20"=>0,"21"=>0,"22"=>0,"23"=>0);
foreach($access as $value){switch($value){case '00':$line['00'] ++;break;case '01':$line['01'] ++;break;case '02':$line['02'] ++;break;case '03':$line['03'] ++;break;case '04':$line['04'] ++;break;case '05':$line['05'] ++;break;case '06':$line['06'] ++;break;case '07':$line['07'] ++;break;case '08':$line['08'] ++;break;case '08':$line['08'] ++;break;case '10':$line['10'] ++;break;case '11':$line['11'] ++;break;case '12':$line['12'] ++;break;case '13':$line['13'] ++;break;case '14':$line['14'] ++;break;case '15':$line['15'] ++;break;case '16':$line['16'] ++;break;case '17':$line['17'] ++;break;case '18':$line['18'] ++;break;case '19':$line['19'] ++;break;case '20':$line['20'] ++;break;case '21':$line['21'] ++;break;case '22':$line['22'] ++;break;case '23':$line['23'] ++;break;}}

$line_list = json_encode($line);
$uu = array_unique($cookie);
$session = array_unique($session);
$bounce = (count($pv) - count($referrer))/ count($pv) * 100;
$exit = (count($pv) - count($session))/ count($pv) * 100;
$avgtime = array_sum($avgtime) / count($avgtime);
$time = s2h($avgtime);
function s2h($avgtime){
  $hours = floor($avgtime / 3600);
  $minutes = floor(($avgtime / 60)%60);
  $seconds = $avgtime % 60;
  $hms = sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
  return $hms; 
}
?>
<style>
.flex-container {
  display: flex;
}
.flex-1{
  flex:1;
}
.flex-2{
  flex:4;
}
#pie {
 height:190;
 width:190;
}
#line {
 height:200;
 width:750;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js"></script>
<h1>アナリティクス</h1>
<div class="flex-container">
<div class="flex-1">
  <ul>
    <li><a href="">Audience</a></li>
    <li><a href="">Acuisition</a></li>
    <li><a href="">Behavior</a></li>
  </ul>
</div>
<div class="flex-2">
<?php echo $date1 ." ~ ".$date2 ."<br><br>"; ?>
<div id="line">
<canvas id="myLine" width="750" height="200"></canvas>
</div>
<div id="pie">
<canvas id="myChart" width="200" height="200"></canvas>
</div>
<?php
echo "<br>Users: ".count($uu)."<br>";
echo "Session: ".count($session)."<br>";
echo "Pageviews: ".count($pv)."<br>";
echo "avg time: " .$time."<br>";
echo "Bounce rate :" .sprintf('%.2f',$bounce)."%<br>";
echo "Exit rate:" .sprintf('%.2f',$exit)."%<br>";
?>
</div>
</div>

<script>
  var visit = JSON.parse('<?php echo $visit; ?>');
  console.log(visit);
  var ctx = document.getElementById("myChart").getContext('2d');
  var myChart = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: ["New", "Returned"],
    datasets: [{
      backgroundColor: [
        "#2ecc71",
        "#3498db",
      ],
      data: [visit['New User'],visit['Returned User']]
    }]
  }
});
var line = JSON.parse('<?php echo $line_list; ?>');
console.log(line);
var ctx2 = document.getElementById("myLine").getContext('2d');
var myLine = new Chart(ctx2, {
   type: 'line',
   data: {
      labels: ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12","13","14","15","16","17","18","19","20","21","22","23","24"],
      datasets: [
      {
         label: "時間別Page View",
         borderColor: 'rgb(0, 153, 255)',
         backgroundColor: "#D9E5FF",
         lineTension: 0,
         data: [line['00'], line['01'],line['02'],line['03'],line['04'],line['05'],line['06'],line['06'],line['07'],line['08'],line['09'],line['10'],line['11'],line['12'],line['13'],line['14'],line['15'],line['16'],line['17'],line['18'],line['19'],line['20'],line['21'],line['22'],line['23']],
      },
      ]
   },
   options: {
      responsive: true,
      scales: {
        yAxes: [{
          ticks: {
            // max: Math.max.apply(null, line)*1.2,
          }
        }]
      }
   }
});
</script>

う~ん、なんだろう、この何とも言い難い感じは。。。

1.各指標はボックスレイアウトで表示したい。
2.日付は選択式にしたい
-> gaだと、日付選択は、GETパラメーター使ってますね。
_u.date00=20180420&_u.date01=20180423/

cssをつける

そんなに悪くないような気がしないでもない。

時間ごとの配列をつくる

絶対、もっとうまく書ける筈なんだが。。。

foreach ($cursor as $document) {
  // var_dump($document);
  $pv[] = $document->date;
  $cookie[] = $document->cookie;
  $session[] = $document->session;
  if(!is_null($document->referrer)){
  $avgtime[] = $document->avgtime;
  }
  if(!is_null($document->referrer)){
  $referrer[] = $document->referrer;
  }
  $visit[] = $document->visit;
  $access[] = substr($document->date, 11, 2);
}

$line = array("00"=>0,"01"=>0, "02"=>0,"03"=>0,"04"=>0,"05"=>0,"06"=>0,"07"=>0,"08"=>0,"09"=>0,"10"=>0,"11"=>0,"12"=>0,"13"=>0,"14"=>0,"15"=>0,"16"=>0,"17"=>0,"18"=>0,"19"=>0,"20"=>0,"21"=>0,"22"=>0,"23"=>0);
foreach($access as $value){switch($value){case '00':$line['00'] ++;break;case '01':$line['01'] ++;break;case '02':$line['02'] ++;break;case '03':$line['03'] ++;break;case '04':$line['04'] ++;break;case '05':$line['05'] ++;break;case '06':$line['06'] ++;break;case '07':$line['07'] ++;break;case '08':$line['08'] ++;break;case '08':$line['08'] ++;break;case '10':$line['10'] ++;break;case '11':$line['11'] ++;break;case '12':$line['12'] ++;break;case '13':$line['13'] ++;break;case '14':$line['14'] ++;break;case '15':$line['15'] ++;break;case '16':$line['16'] ++;break;case '17':$line['17'] ++;break;case '18':$line['18'] ++;break;case '19':$line['19'] ++;break;case '20':$line['20'] ++;break;case '21':$line['21'] ++;break;case '22':$line['22'] ++;break;case '23':$line['23'] ++;break;}}
var_dump($line);

悔しいですね。

折れ線グラフをつくる

まず、仮データでつくる。

<style>
#line {
 height:200;
 width:750;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js"></script>
<div id="line">
<canvas id="myChart" width="750" height="200"></canvas>
</div>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
   type: 'line',
   data: {
      labels: ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12","13","14","15","16","17","18","19","20","21","22","23","24"],
      datasets: [
      {
         label: "Page View",
         borderColor: 'rgb(0, 153, 255)',
         backgroundColor: "#D9E5FF",
         lineTension: 0,
         data: [20, 26, 12, 43, 33, 21, 29, 5, 5, 0, 1,2,2, 3, 4, 5, 5, 5,6, 7, 22, 23, 15, 100, 24],
      },
      ]
   },
   options: {
      responsive: true,
      scales: {
        yAxes: [{
        	ticks: {
            max: 110,
          }
        }]
      }
   }
});
</script>

データラベルが00~24なので、countしたいが、どう組めば一番早い?

新規ユーザーとリターンユーザーを表示する

$visit = json_encode(array_count_values($visit))を配列で渡して、
chart.jsで表示する。

  var visit = JSON.parse('<?php echo $visit; ?>');
  console.log(visit);
  var ctx = document.getElementById("myChart").getContext('2d');
  var myChart = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: ["New", "Returned"],
    datasets: [{
      backgroundColor: [
        "#2ecc71",
        "#3498db",
      ],
      data: [visit['New User'],visit['Returned User']]
    }]
  }
});

ここまではそんなに難しくないんだが、次が問題。
(1)時間ごと、もしくは(2)日付ごとのアクセスを棒グラフで表示する。
まず分けて考えよう。

1.時間ごとの場合
->chart.jsのラベルは24時間
->訪問時間 y:m:d h:m:s の該当するhの数をcountしてjsonにencodeする

2.日付ごとの場合
->ラベルは期間の日付
->訪問時間 y:m:d h:m:s の該当するy:m:dの数をcountしてjsonにencodeする

ややこしいので、時間から作る。

平均滞在時間の計算

array_sumをcountで割った数をh:m:sに変換します。

$avgtime = array_sum($avgtime) / count($avgtime);

$time = s2h($avgtime);
function s2h($avgtime){
  $hours = floor($avgtime / 3600);
  $minutes = floor(($avgtime / 60)%60);
  $seconds = $avgtime % 60;
  $hms = sprintf("%02d:%02d:%02d", $hours, $minutes, $seconds);
  return $hms; 
}

次は、new user とreturn user

analyticsを設計していく

初期画面

<?php

// $date1 = date("Y-m-d H:i:s", strtotime("- 6 day"));
$date1 = date("Y-m-d", strtotime("0 day"));
// $date2 = date("Y-m-d H:i:s", strtotime("- 1 day"));
$date2 = date("Y-m-d H:i:s");


$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$filter =  &#91;
	'date' => [ '$gte' => $date1, '$lte' => $date2]
];
$options = [
  'projection' => ['_id' => 0],
  'sort' => ['_id' => -1],
];
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $mng->executeQuery('app.na007', $query);

foreach ($cursor as $document) {
  // var_dump($document);
  $pv[] = $document->date;
  $cookie[] = $document->cookie;
  $session[] = $document->session;
  if(!is_null($document->referrer)){
  $referrer[] = $document->referrer;
  }
}
// var_dump($session);
$uu = array_unique($cookie);
$session = array_unique($session);
$bounce = (count($pv) - count($referrer))/ count($pv) * 100;
$exit = (count($pv) - count($session))/ count($pv) * 100;
?>
<style>
.flex-container {
  display: flex;
}
.flex-1{
  flex:1;
}
.flex-2{
  flex:4;
}
</style>
<h1>アナリティクス</h1>
<div class="flex-container">
<div class="flex-1">
  <ul>
    <li><a href="">Audience</a></li>
    <li><a href="">Acuisition</a></li>
    <li><a href="">Behavior</a></li>
  </ul>
</div>
<div class="flex-2">


<?php
echo $date1 ." ~ ".$date2 ."<br>";
echo "<br>Users :".count($uu)."<br>";
echo "Pageviews :".count($pv)."<br>";
echo "Bounce rate :" .sprintf('%.2f',$bounce)."%<br>";
echo "Exit rate:" .sprintf('%.2f',$exit)."%<br>";
?>
</div>
</div>

必要項目
-average session duration
-時間別のユーザー数(折れ線グラフ)
-return userとnew user(円グラフ)

google analyticsのソースを見ると、json.parseして、jsに値を渡しています。

visualizationで、corechartというパッケージをloadしているように見えます。

// TODO(abdussabur): Lazily load gViz instead.
      // NOTE: Due to a conflict with galaxy's copy of gviz, the geochart does not work in GAFE4.
      // See cl/145118637 for more information.
      google.load('visualization', '1', {packages:['corechart', 'table']});
      (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','https://www.google-analytics.com/analytics.js','gaAPI');

      // Tracking codes are being used in tracking-service.js . Please keep them in sync.
      gaAPI('create', 'UA-hoge', 'auto');
      gaAPI('create', 'UA-hoge', 'auto', {'name': 'ta'});
      gaAPI('create', 'UA-hoge', 'auto', {'name': 'tw'});

これのjsはなにしてるんだ?
https://ssl.gstatic.com/analytics/20180419-00/app/js/js.js

monoを使う

昔入れたmono、versionは4.8.0です。

[vagrant@localhost csharp]$ . /opt/mono/env.sh
[vagrant@localhost csharp]$ mono --version
Mono JIT compiler version 4.8.0 (Stable 4.8.0.495/e4a3cf3 Thu Feb 23 18:33:47 UTC 2017)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        LLVM:          yes(3.6.0svn-mono-/)
        GC:            sgen

cs

using System;

class MyApp {

	static void Main(){
		Console.WriteLine("Hello World");
	}
}

compileはmcs

[vagrant@localhost csharp]$ mcs MyApp.cs
[vagrant@localhost csharp]$ ls
MyApp.cs  MyApp.exe
[vagrant@localhost csharp]$ mono MyApp.exe
Hello World
using System;

class MyApp {

	static void Main(){
		string msg = "Hello csharp";
		Console.WriteLine(msg);
	}
}

定数:const string msg = “Hello csharp”;

visual studio

inputとtodoが多すぎて混乱してきた。
1.mongo DBを使ってanalyticsをつくる
2.c# + visual studioでazure cosmosDBに接続する
3.c#でアプリケーションをつくって、azureで公開する

-> c#、visual studioは基本から学ばなければならないので、習得しながら疑似GAの完成までもっていくには恐らく時間がかかりすぎる
-> azure + c# は慣れるまではもっと簡単なテーマ・アプリケーションから作りたい
-> まずは analyticsは VPS + PHP + mongoDB + chart.jsで作り上げる

よし、これで行こう!

cyberduckでazure app serviceにftp接続する

(1)app serviceのデプロイ資格情報でname、passを入力する

(2)概要->発行プロファイルの取得 でpublish settingファイルを取得する

<publishProfile profileName="nanalytics - FTP" publishMethod="FTP" publishUrl="ftp://hoge.ftp.azurewebsites.windows.net/site/wwwroot" ftpPassiveMode="True" userName="hoge" userPWD="hogehoge" destinationAppUrl="http://nanalytics.azurewebsites.net" SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink="http://windows.azure.com" webSystem="WebSites"><databases /></publishProfile>

(3)ファイル転送ツール等で、サーバーは発行プロファイルのpublishUrl、ユーザー名はuserName、パスワードはuserPWDを入れる。ポートは21でOK

(4)webrootに接続完了! timezoneが-9H(GMT)になってますね。