GAミント至上主義

Web Monomaniacal Developer.

Vue.jsからGTMを使ってGAのイベントを送る

ブログタイトルのGAはGoogle Analytics(以下GA)ではないですが、Google Tag Manager(以下GTM)でGAを読み込んでいる場合、独自イベントの送信がちょっと面倒です。

下記のようなVueプラグインもあるけど、Vue.jsの環境はVue CLI 3で、GTMのタグはindex.htmlに公式通りに入れているため、今回はスルーした。

www.npmjs.com

dataLayerを使う

GTMから独自変数を送るにはdataLayerというグローバル変数を使うらしい。

Developer Guide  |  Google Tag Manager for Web Tracking  |  Google Developers

dataLayerを制するものはGTMを制す - Qiita

こんな感じでなんでも送れる。

dataLayer.push({'event': 'event_name'});

dataLayer.push({
  'color': 'red',
  'conversionValue': 50,
  'event': 'customizeCar'
});

シンプルなVueプラグインを作る

とりあえずエラーイベントを送るように下記のような感じで作った。
category, action, labelはGAのイベントと合わせた。

gtm-datalayer.js

const gtmDataLayer = {
  install: function (Vue, options) {
    const dataLayer = window.dataLayer || []
    Vue.prototype.$gtm = {
      sendErrorEvent: function(category, action, label){
        dataLayer.push({
          event: 'error',
          eventCategory: category || 'defaultCategory',
          eventAction: action || 'defaultAction',
          eventLabel: label || 'defaultLabel'
        })
      }
    }
  }
}
export default gtmDataLayer

基本的にGTMのタグはHTMLの上の方で先に読み込んでいるはずで、dataLayerがセットされていないことはないはずだけど念の為、dataLayerがなくてもエラーが起きない(何も起きない)ようにしている。クリティカルな場面では使わないはず。

main.jsでインストールする

import GtmDataLayer from './plugins/gtm-datalayer'
Vue.use(GtmDataLayer)

これでvueのscript内から

this.$gtm.sendErrorEvent('お好きなカテゴリ', 'お好きなアクション', 'お好きなラベル')

みたいな感じで使える。

GTMで変数追加

勝手に送った変数はそのままでは使えない

ユーザー定義変数に上記、eventCategory、eventAction、eventLabelを追加する

f:id:uyamazak:20181114174848p:plain

GTMでカスタムイベント追加

カスタムイベントを受け取るトリガーを追加する。
f:id:uyamazak:20181114175009p:plain

とりあえず「すべてのカスタムイベント」にしたけど、あとで分けるなら、追加した変数を指定すればよさそう。

GTMでGAイベントのタグを追加

上で作った変数とトリガーを使って作る。
f:id:uyamazak:20181114175206p:plain

あとは公開するだけ。

Vue.js側から送信

これで送る。
今回はヤギが渡したはがきを食べた場面で送るようにした

//省略
  methods: {
    sampleError: function(){
      this.$gtm.sendErrorEvent('yagi', 'eat', `yagi ate postcard! ${this.eatCount}: ${this.content}`)
    }
  }
//省略

GAのリアルタイムイベントで確認

f:id:uyamazak:20181114175826p:plain

取れた。

イベント名を汎用的なものに変更(2018/11/16追記)

GTM側のGTMのトリガーのイベント名をerrorで作ってしまったけど、エラーに限らず汎用的に使えるのでappEventに変更し、エラーはCategoryを使うようにしてみた。

const EVENT_NAME = 'appEvent'
const gtmDataLayer = {
  install: function (Vue, options) {
    const dataLayer = window.dataLayer || []
    Vue.prototype.$gtm = {
      sendError: function(action, label){
        dataLayer.push({
          event: EVENT_NAME,
          eventCategory: 'appError',
          eventAction: action || 'defaultAction',
          eventLabel: label || 'defaultLabel'
        })
      }
    }
  }
}
export default gtmDataLayer

これで、エラーを送るときはカテゴリはappErrorで固定、actionとlabelだけ指定すればよくなった。actionに要約、labelに詳細みたいな感じで書けるので使いやすそう。

this.$gtm.sendError('yagiEte', `yagi ate postcard! count:${app.eatCount}, message:${tmpContent}`)

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

GCP HTTPSロードバランサーにGoogleマネージドSSL証明書(β)を使う

βリリースされていることに今更気づきました。
GAEやFirebase HostingでもマネージドSSL証明書は追加されていたのでやっと来たという感じです。

f:id:uyamazak:20181112120529p:plain

ドキュメントはまだ英語のみ?
Creating and Using SSL Certificates  |  Load Balancing  |  Google Cloud


これまでは下記自作のスクリプト+ライブラリと開発サーバーのcronで回してきましたがいらなくなりそう。
GitHub - uyamazak/gcp-ssl-auto-renewer: Auto renew SSL Certificates commands on Google Cloud Platform (GCP).

作成自体もUI(Cloud Console)で出来るようになっていました。

ロードバランサーの詳細」→「編集」→「フロントエンドの設定」→「プロトコル:HTTPS」→「証明書」で新しい証明書を追加できます。

f:id:uyamazak:20181112120521p:plain
f:id:uyamazak:20181112120530p:plain

プロビジョニング(セットアップ)に時間がかかり、その間は無効になってしまうので、稼働中のサービスは切り替えでなく、「その他の証明書」に追加でやればよさそう。
現在テストのため、手動で上げたものを「証明書」に、マネージドを「その他の証明書」追加した。

追加した場合どの証明書が使われるかはよくわからない。さっきブラウザで確認すると、マネージドの方が使われてた。
後日勇気を出してマネージドのみにしてみようと思う(影響の少ないドメインで)。

gcoudコマンドだと下記のような感じでステータスを確認できる。

% gcloud beta compute ssl-certificates list --project=<your-project-name>
NAME                      TYPE          CREATION_TIMESTAMP             EXPIRE_TIME                    MANAGED_STATUS
api-yagish-managed2       MANAGED       2018-11-11T18:39:18.120-08:00  2019-02-09T17:54:58.000-08:00  ACTIVE api.yagish.jp: ACTIVE

Let's Encryptの無料化と自動更新による恩恵は世界中のエンジニアの人件費として金額化したらとてつもないことになりそう。

複数ドメイン

Let's Encryptでは一つの証明書で複数ドメインを扱えるし、Cloud ConsoleのUI上も追加できるようになってるけど
f:id:uyamazak:20181115102408p:plain
追加すると怒られるという謎。今後できるようなるのかもしれない。
現状でも9個まで追加できるみたいなので、ほとんど問題にはならないと思う。

【解決】puppeteerを1.10にするとPDFの日本語が文字化けする問題

2018/11/13 追記 結論

Chromium 72.0.3606.0(Developer Build)を使ったところ直ったので、次のバージョン(1.11)では直るはず。
そのため1.10をスキップするだけで問題は解決しそう。

追記ここまで


yagish履歴書のHTML→PDF変換で使っているpuppeteerのバージョンを1.8.0から1.10.0にしたところ、PDFで日本語が表示できなくなった。
Ubuntu16.04上のDockerで動かしており、puppetter以外の違いはないこと、screenshotの画像は問題なく日本語が表示されるので、フォントのインストールなどは関係なさそう。

github.com

リリース情報を見ると、1.9まではChromium 71、1.10からChromium 72を使うようになったのでそこが原因っぽい。
1.9も試したところ問題なかった。
またChromiumではなく別途インストールしたChrome70を、1.10から使った場合も大丈夫だった。

Releases · GoogleChrome/puppeteer · GitHub

生成されたPDFをChromeで開くと問題なく表示されるが、Acrobatで開くと下記のように警告がでる。

f:id:uyamazak:20181109130551p:plain

PDFへのフォントの埋め込みがうまくいってない?

2018/11/9 14時追記

GihHubのissueを見ていたら文字化けではないけどハングするというのを見つけた。

Puppeteer 1.10.0 hangs When Generating PDF of HTML Drawing Context in Docker Container · Issue #3516 · GoogleChrome/puppeteer · GitHub

引き続き調査中

2018/11/13 追記

puppeteerとChrome側をいくつか差し替えて確認

ということでChromiuimバージョン72が日本語が表示できない原因である確率がかなり高そう。
1.10 + Chromeで動かす選択肢もあるが、バージョンは揃えた方がいいというのもどっかに書いてあったので、puppeteer1.9を指定してインストールして使うのが今のところ一番良さげ。

Chromium 72 をUbuntuの入っているノートPCで動かそうと思ったけど、apt-getだと70しか入れられず、なかなか面倒。

Developer Buildはバージョン72.0.3606.0、ビルド済みで簡単にダウンロード&実行できたので、Yahoo!トップページをPDF化したところ、問題なく日本語フォントは埋め込まれ表示されてた。

Developer Buildは下記ページをブラウザの開発者ツールでUALinuxのものにしたらLinux版がダウンロードできる。
download-chromium.appspot.com

使用したUA

Mozilla/5.0 (X11; Ubuntu; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36

Developer Buildとpuppeteer同梱(72.0.3582.0)は細かいバージョン差があるため、Chromium72自体ではなく、puppeteer1.10との組み合わせの問題なのか、まだ確信が持てない。

そのため下記2つを試す。

  • puppeteer 1.9 + Chromium 72.0.3606.0(Developer Build) → OK
  • puppeteer 1.10 + Chromium 72.0.3606.0(Developer Build) → OK

なんとChromiumを最新の開発版にするだけで直ってしまった。つまりこのバグはChromium(72.0.3582.0)のもので、開発版ではすでに修正されているみたい。
puppeteer 1.11にはこの直ったChromiumが同梱されるはずなので1.10はスルーして1.11を待つことにする。

だいぶ遠回りしたけど、Chromiumのバージョン違いでこんなこともあるんだと勉強になった希ガス