[Go] Firebaseとの連結

Firebaseで Firestoreを作成する

import (
	"fmt"

	firebase "firebase.google.com/go"
    "google.golang.org/api/option"
)

func main(){
	fmt.Printf("Hello Firestore")
}

必要な依存関係を追加
$ go get firebase.google.com/go

あれ? 上手くいかんな。。。

[python3] googletransで日本語->英語に翻訳する

$ sudo pip3 install googletrans
Successfully installed chardet-3.0.4 contextvars-2.4 googletrans-3.0.0 h11-0.9.0 h2-3.2.0 hpack-3.0.0 hstspreload-2020.12.22 httpcore-0.9.1 httpx-0.13.3 hyperframe-5.2.0 immutables-0.15 rfc3986-1.4.0 sniffio-1.2.0

# -*- coding: utf-8 -*-
from googletrans import Translator
translator = Translator()

translation = translator.translate("こんにちは", src='ja', dest="en")
print(translation.text)

$ python3 app.py
AttributeError: ‘NoneType’ object has no attribute ‘group’

どうやら3.0.0ではなく、4系が動いているとのこと
$ sudo pip3 uninstall googletrans
$ sudo pip3 install googletrans==4.0.0-rc1

# -*- coding: utf-8 -*-
from googletrans import Translator
translator = Translator()

translation = translator.translate("h音楽アーティストやレコードレーベルが保有する楽曲を NFT 化し世界中に販売", src='ja', dest='en')
print(translation.text)

$ python3 app.py
Music artists and songs owned by record labels NFT and sell worldwide

なかなか凄いな
formからpostして翻訳して返却したいな

[Google Analytics API] PHPでリアルタイムユーザ数を取得して表示する

GA APIでページビューやセッションだけでなく、rt:activeUsersでリアルタイムユーザを取得できる。

require_once '../google-api-php-client/src/Google/autoload.php';
$service_account_email = '*.iam.gserviceaccount.com';
$key = file_get_contents('*.p12');
$profile = '*';

$client = new Google_Client();
$analytics = new Google_Service_Analytics($client);

$cred = new Google_Auth_AssertionCredentials(
  $service_account_email,
  array(Google_Service_Analytics::ANALYTICS_READONLY),
  $key
);

$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()){
  $client->getAuth()->refreshTokenWithAssertion($cred);
}

$optParams = array(
'dimensions' => 'rt:medium');

try {
$results = $analytics->data_realtime->get(
  'ga:' . $profile,
  'rt:activeUsers',
  $optParams);
} catch (apiServiceException $e) {
  $error = $e->getMessage();
}
print("<pre>");
// print_r($results["totalsForAllResults"]["rt:activeUsers"]);
print_r($results);
print("</pre>");

$array[“totalsForAllResults”][“rt:activeUsers”] でアクティブユーザすうを取れるが、配列で何が取れるか確認した方が良い。

GAの場合、analytics.jsでajaxで処理しているので、ELBのアクセスログから例えば過去5分間のアクセス数を数えてログインユーザとして表示するってよりは、GA APIの方が現実的か。

ちなみに、rtって、リツイートの略かと思ったけど、real timeの略っぽいね。なんじゃそりゃw

[reCAPTCHA] 問い合わせフォームをセキュアにする

よくある「ボットではありません」というフォーム。
これを実装したい。

https://www.google.com/recaptcha/admin/create

すると、サイトキーとシークレットキーが生成される。

### HTML側の表示
– g-recaptcha タグ(g-recaptcha クラスを指定した要素)を使って自動的に表示

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>reCAPTCHA widget</title>
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
    <script>
    	var myAlert = function(response){
    		alert("checkbox is checked");
    	};
    </script>
</head>
<body>
	<div class="container">
		<form method="post" action="#">
			<div class="g-recaptcha" data-sitekey="***" data-callback="myAlert"></div>
		</form>
		<script src="https://www.google.com/recaptcha/api.js" async defer></script>
	</div>
	<script>
	</script>
</body>
</html>

dev環境ではなく、ドメイン上で実装します。

ほう、割とすぐ実装できる。

[Laravel8.16.0] Google Analyticsの値をバッチ処理で挿入する

// 1.モデルを作成
$ php artisan make:model Analytic -m

// 2.migration file

    public function up()
    {
        Schema::create('analytics', function (Blueprint $table) {
            $table->id();
            $table->integer('sessions')->nullable();
            $table->integer('pageviews')->nullable();
            $table->timestamps();
        });
    }

$ php artisan migrate
mysql> describe analytics;

// 3.PDO部分を先に作ります

$date = new DateTime();
$date = $date->format('Y-m-d H:i:s');
$sessions = 100;
$pageviews = 200;

$username="*";
$password="*";
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';

try {
  $dbh = new PDO($dsn, $username, $password,array(PDO::ATTR_EMULATE_PREPARES => false,PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`"));
  $sql = "INSERT INTO analytics(
  sessions, pageviews, created_at
  ) VALUES (
    ".$sessions.", ".$pageviews.", '".$date."'
  )";

  $res = $dbh->query($sql);
} catch (PDOException $e) {
  exit('データベース接続失敗。'.$e->getMessage());
}

$dbh = null;

mysql> select * from analytics;
+—-+———-+———–+———————+————+
| id | sessions | pageviews | created_at | updated_at |
+—-+———-+———–+———————+————+
| 1 | 100 | 200 | 2020-12-05 00:37:52 | NULL |
+—-+———-+———–+———————+————+
1 row in set (0.00 sec)

// 4. GoogleAnalyticsAPIを連結
L バッチで処理する際は、required_once と p12ファイルを絶対パスで指定する必要がある。

require_once '/home/vagrant/dev/test/google-api-php-client/src/Google/autoload.php';
$service_account_email = '*.iam.gserviceaccount.com';
$key = file_get_contents('/home/vagrant/dev/test/analytics-*.p12');
$profile = '*';

$client = new Google_Client();
$analytics = new Google_Service_Analytics($client);

$cred = new Google_Auth_AssertionCredentials(
  $service_account_email,
  array(Google_Service_Analytics::ANALYTICS_READONLY),
  $key
);

$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()){
  $client->getAuth()->refreshTokenWithAssertion($cred);
}

$result = $analytics->data_ga->get(
  'ga:' . $profile,
  'yesterday',
  'yesterday',
  'ga:sessions,ga:pageviews',
);
$sessions = $result -> rows[0][0];
$pageviews = $result -> rows[0][1];

mysql> select * from analytics;

$ sudo chmod 755 batch.php

// 5.Cronの設定
$ which php
/usr/bin/php

$ sudo vi /etc/crontab

*/1 * * * * /usr/bin/php /home/vagrant/dev/testApp/batch.php

mysql> select * from analytics;

$ sudo tail -f /var/log/cron でcronログ見るとエラーは出てないのに、mysqlにデータが入ってなくてなんでかと思ったが、required_once と p12ファイルを絶対パスで指定していなかったのが原因だったみたい。難儀なこっちゃ。

[Laravel8.16.0] Google Analytics APIを使う

まず、analytics-*-*.p12ファイルですが、publicには置けないので、resourcesフォルダの下にstaticフォルダを作成し、そこに置きます。
※storageやpublicに置かない様にする。

続いて、google-api-php-clientをインストールします。
githubで最新を確認する。この記事を書いている時点では^2.7が最新です。
https://github.com/googleapis/google-api-php-client

$ composer require google/apiclient:”^2.7″

AdminController.php (*test)
L resource_path(‘static/analytics-*-*.p12’)で、p12を指定する

    public function index(){

        $client = new Google_Client();
        $client->setApplicationName("Client_Library_Examples");
        $client->setDeveloperKey(resource_path('static/analytics-*-*.p12'));
        dd($client->getAccessToken());

    	$user = Auth::user();
        return view('admin.index',compact('user'));
    }

nullが返ってくるとOKっぽい。

テスト環境と同じ様に書いてみます。

use Google_Client;
use Google_Service_Analytics;

$service_account_email = '*.iam.gserviceaccount.com';
      $key = file_get_contents(resource_path('static/analytics-*-*.p12'));
      $profile = '*';

      $client = new Google_Client();
      $analytics = new Google_Service_Analytics($client);

      $cred = new Google_Auth_AssertionCredentials(
        $service_account_email,
        array(Google_Service_Analytics::ANALYTICS_READONLY),
        $key
      );

      $client->setAssertionCredentials($cred);
      if($client->getAuth()->isAccessTokenExpired()){
        $client->getAuth()->refreshTokenWithAssertion($cred);
      }

Class ‘App\Http\Controllers\Google_Auth_AssertionCredentials’ not foundのエラー

issueに原因が載ってます。
https://github.com/GoogleCloudPlatform/nodejs-docs-samples/issues/158

Oh, I've just found https://github.com/google/google-api-php-client/blob/master/UPGRADING.md

So it's the docs at https://developers.google.com/analytics/devguides/reporting/core/v3/quickstart/service-php that are wrong.

GoogleDevコンソールで、「サービス アカウント キーの作成」からjsonファイルを作成して、以下に書き換えます。

use Google_Client;
use Google_Service_Analytics;

$profile = '*';

        $client = new Google_Client();
        $client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));

        $client->setSubject('*.iam.gserviceaccount.com');
        $client->setAuthConfig(array(
            'type' => 'service_account',
            'client_email' => '*.iam.gserviceaccount.com',
            'client_id' => '*',
            'private_key' => "-----BEGIN PRIVATE KEY-----***-----END PRIVATE KEY-----\n"
        ));

        $analytics= new Google_Service_Analytics($client);

         $result = $analytics->data_ga->get(
         'ga:' . $profile,
         'yesterday',
         '0daysAgo',
         'ga:pageviews',
         array(
           // "dimensions" => 'ga:pageTitle',
           "dimensions" => 'ga:pagePath',
           "sort" => '-ga:pageviews',
           "max-results" => '10',
         )
        );

        $data = $result->rows;
        dd($data);

これでいけました。結局p12は使わない。
う〜ん、AnalyticsAPIは使うの緊張する。

[Google Analytics API] Chart.jsでユーザ範囲指定のPVを表示したい

まずChart.jsの復習から
公式ドキュメントを元にテスト表示します。

<body>
	<h1>折れ線グラフ</h1>
	<div >
		<canvas id="myLineChart" width="400" height="200"></canvas>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
	<script>
		var ctx = document.getElementById('myLineChart').getContext('2d');
		var chart = new Chart(ctx, {
			type: 'line',

			data: {
				labels: ['january', 'February', 'March', 'April', 'May', 'June', 'July'],
				datasets: [{
					label: 'ページビュー',
					backgroundColor: 'rgb(0, 0, 0, 0)',
					borderColor: 'rgb(81, 203, 206)',
					data: [0, 10, 5, 2, 20, 30, 45],
				}]
			},

			options: {
				responsive: false
			}
		});
	</script>
</body>
</html>

PHP側から日付とpageviewsの配列をjasonでjs側に渡す

$result = $data -> rows;
foreach($result as $key => $value){
  $date[] = $value[0];
  $pageviews[] = $value[1];
}
$date = json_encode($date);
$pageviews = json_encode($pageviews);

js側でJSON.parseで受け取る

data: {
        labels: JSON.parse('<?php echo $date; ?>'),
        datasets: [{
          label: 'ページビュー',
          lineTension: 0,
          backgroundColor: 'rgb(0, 0, 0, 0)',
          borderColor: 'rgb(81, 203, 206)',
          data: JSON.parse('<?php echo $pageviews; ?>'),
        }]
      },

日付をYYYYMMDDではなく、本家のanalyticsみたいにMM月DD日にしたい。
-> substrでMMとDDを切り抜く

foreach($result as $key => $value){
  $date[] = substr($value[0], 4, 2) . "月" . substr($value[0], 6) . "日";
  $pageviews[] = $value[1];
}

これをユーザ入力で表示させます。

if(isset($_GET['datepicker_s']) && $_GET['datepicker_s'] !== ""){
  $start_day = $_GET['datepicker_s'];

  if(isset($_GET['datepicker_e']) && $_GET['datepicker_e'] !== ""){
    $end_day = $_GET['datepicker_e'];
  } else {
    $end_day = date("Y-m-d");
  }

} else {
  if(isset($_GET['datepicker_e']) && $_GET['datepicker_e'] !== ""){
    $start_day = date("Y-m-d",strtotime("-1 week",  strtotime($_GET['datepicker_e'] . " 00:00:00")));
    $end_day = $_GET['datepicker_e'];
  } else {
    $start_day = date("Y-m-d",strtotime("-1 week"));
    $end_day = date("Y-m-d");
  }
}

chartjsのtypeがlineだと、datasetが1つの時、以下の様にバグになってしまう。

type=”bar”とする

うーん、悪くないけど、やっぱ棒グラフが良いな

[Google Analytics API] 日付別のPVを取得したい

dimensionをga:dateにして、metricsをga:pageviewsにする。
$data[“rows”][0][“date”][“pv”] みたいな感じで返ってくるので、一度、rowsを取得してから、foreachで回すとdateとpvを取得できる。

$start_day = date("Y-m-d",strtotime("-1 week"));
$end_day = date("Y-m-d");


$data = $analytics->data_ga->get(
  'ga:' . $profile,
  $start_day,
  $end_day,
  'ga:pageviews',
 array(
   "dimensions" => 'ga:date',
   "metrics" => 'ga:pageviews',
   "sort" => 'ga:date',
  )
);
$result = $data -> rows;
foreach($result as $key => $value){
 echo  '日付:' . $value[0]. ' PV:' . $value[1] . "<br>";
}

うん、これをchart.jsで表示したい。できれば、ユーザがformで日付(開始日、終了日)を入力して、それを表示。
PHPからJavascriptにjsonで渡して表示でOKだと思うんだが、Chart.jsの書き方忘れたから復習からだ。

[Google Analytics API] ユーザが範囲指定した値のデータを表示する

– ユーザが範囲指定した期間のPV、セッション、上位閲覧ページを表示したい。
– UIとしては以下のように、開始日と終了日のDatepickerがある。

### form
まず、formはgetメソッドで作成する

<form action="" method="get">
      <div class="search">
      <div class="form-group form-inline ">
        <label for="" class="">注文日</label>
        <input type="text" class="form-control" name="datepicker_s" placeholder="">
        <label for="" class=""> ~ </label>
        <input type="text" class="form-control" name="datepicker_e" placeholder="">
        <button type="submit" class="btn">検索</button>
      </div>
      </div>
    </form>

### js
– 開始日は終了日より以前、終了日は開始日より以降 をjsのon changeで制御する
– 開始日、終了日共にmaxDateは今日までとする

<script
  src="https://code.jquery.com/jquery-3.5.1.js"
  integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
  crossorigin="anonymous"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
  	<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
  	<script>
    $(function(){
      var format = 'yy-mm-dd';

      var start = $("[name=datepicker_s]").datepicker({
        dateFormat: 'yy-mm-dd',
        maxDate: '0'
      }).on("change", function(){
        end.datepicker("option", "minDate", getDate(this));
      });

      var end = $("[name=datepicker_e]").datepicker({
        dateFormat: 'yy-mm-dd',
        maxDate: '0',
      }).on("change", function(){
        start.datepicker("option", "maxDate", getDate(this));
      });

      function getDate(element){
        var date;
        try {
          date = $.datepicker.parseDate(format, element.value);
        } catch(error){
          date = null;
        }
        return date;
      }
    });
  </script>

### php
– (1)開始日、終了日入力なし、(2)開始日のみ入力、(3)終了日のみ入力、(4)開始日、終了日入力あり の4パターンを書いてやれば良い
– 「終了日のみ入力」の際に、開始日をいつに設定するかは決めの問題。便宜上、下では終了日の一週間前にしている

if(isset($_GET['datepicker_s']) && $_GET['datepicker_s'] !== ""){
  $start_day = $_GET['datepicker_s'];

  if(isset($_GET['datepicker_e']) && $_GET['datepicker_e'] !== ""){
    $end_day = $_GET['datepicker_e'];
  } else {
    $end_day = date("Y-m-d");
  }

} else {
  if(isset($_GET['datepicker_e']) && $_GET['datepicker_e'] !== ""){
    $start_day = date("Y-m-d",strtotime("-1 week",  strtotime($_GET['datepicker_e'] . " 00:00:00")));
    $end_day = $_GET['datepicker_e'];
  } else {
    $start_day = date("Y-m-d",strtotime("-1 week"));
    $end_day = date("Y-m-d");
  }
}

$data = $analytics->data_ga->get(
  'ga:' . $profile,
  $start_day,
  $end_day,
  'ga:pageviews',
);
$pv = $data -> rows[0][0];

この分岐処理は、ハマると時間がかかるんだよなー

[Google Analytics API] タイトルとURLをPV順にソートして表示

この辺を押さえておけば大丈夫そう
訪問数: ga:sessions
合計PV: ga:pageviews
平均閲覧ページ数: ga:pageviewsPerSession
平均滞在時間: ga:avgSessionDuration
直帰率: ga:bounceRate

タイトル: ga:pageTitle
パス: ga:pagePath

require_once 'google-api-php-client/src/Google/autoload.php';
$service_account_email = '*';
$key = file_get_contents('analytics-*-*.p12');
$profile = '*';

$client = new Google_Client();
$analytics = new Google_Service_Analytics($client);

$cred = new Google_Auth_AssertionCredentials(
	$service_account_email,
	array(Google_Service_Analytics::ANALYTICS_READONLY),
	$key
);

$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()){
	$client->getAuth()->refreshTokenWithAssertion($cred);
}

$pv = $analytics->data_ga->get(
	'ga:' . $profile,
	'7daysAgo',
	'yesterday',
	'ga:pageviews',
);
echo $pv -> rows[0][0] . "\n";


$result = $analytics->data_ga->get(
	'ga:' . $profile,
	'7daysAgo',
	'yesterday',
	'ga:pageviews',
	array(
		// "dimensions" => 'ga:pageTitle',
		"dimensions" => 'ga:pagePath',
		"sort" => '-ga:pageviews',
		"max-results" => '10',
	)
);

$data = $result->rows;

foreach($data as $key => $row){
	echo  ($key + 1) . ':' . $row[0]. ' ' . $row[1] . "\n";
}

ちょっと処理に時間がかかるので、テーブル作ってトップページの値はCronでデータベースに格納しておくか。
あとは日付指定のところをDatepicker & Postで作りたい。
todayは0daysAgo, yesterdayは’1daysAgo’でもいけるみたいだけど、[0-9]+(daysAgo)は9日前までしかできないから、YYYY-MM-DDの方が良さそうですね。
[0-9]{4}-[0-9]{2}-[0-9]{2}|today|yesterday|[0-9]+(daysAgo)

https://developers.google.com/analytics/devguides/reporting/core/v3/reference?hl=ja