完成したコード
早速ですが、完成したコードを以下に示します。
既存の Google Analytics コードを以下に置き換えて下さい。
同意を求める通知を表示するJavascript
同意を求める通知を出すための Javascript です。HTML に手を加える必要はないので既存ページにポン付けでOKです。
localstrage を使って一度同意 (or 拒否) を得たらその後は表示を出さないようにしています。
海外からのアクセスを考慮して、日本語と英語を表示できるようにしています。
ユーザの言語設定取得については後述します。(PHP や Javascript を使います)
トラッキングIDは Google Analytics の管理画面から確認するか、既に設置済みのコードから "UA-*********-*" というものを探して使って下さい。
/*
* Google Analytics をユーザの同意が得られてから有効にする
* GDPR 対策
*/
/*
* 言語設定はwindow.useLangに保存してある値を使う
*/
window.addEventListener("DOMContentLoaded", function(){
// gtagのオブジェクト、関数を定義
// この時点ではトラッキングは開始されない
window.dataLayer = window.dataLayer || [];
window.gtag = function(){
dataLayer.push(arguments);
};
// localStorage から ga_cookie_opt_in の値を取得
var userGanalyticsOptin = localStorage.getItem('ganalytics_gdpr_optin');
// console.log(userGanalyticsOptin);
// localStrageに保存された値に応じてGoogleAnalyticsの有効/無効/確認を分岐する
if(userGanalyticsOptin === "no"){
// 保存された値が"no"ならGoogleAnalyticsを実行しない
// (トラッキングを発行しない)
// 何もせずに終了
} else if(userGanalyticsOptin === "yes"){
// 保存された値が"yes"ならGoogleAnalyticsを実行する
// (トラッキングを発行する)
// トラッキング設定とgtag.jsの読み込み
gtag("js", new Date());
gtag("config", "UA-*********-*"); // トラッキングID
var gtagjs = document.getElementsByTagName("head")[0].appendChild(document.createElement("script"));
gtagjs.src = "https://www.googletagmanager.com/gtag/js?id=UA-*********-*"; // トラッキングID
} else{
// 保存された値がない場合は一旦 Google Analytics を無効にして通知を表示
// 通知バーのCSS読込
var acceptcss = document.createElement("link");
acceptcss.href = "通知バーのCSSファイルパス (/ganalytics_gdpr.css)";
acceptcss.setAttribute("rel", "stylesheet");
document.head.appendChild(acceptcss);
//通知の表示
var accept = document.body.appendChild(document.createElement("div"));
accept.className = "check-accept-google-analytics";
var wrapper = accept.appendChild(document.createElement("div"));
var notice = wrapper.appendChild(document.createElement("p"));
notice.innerHTML = (window.useLang === "ja" ?
[
"このサイトでは Google Analytics で Cookie を使用した Web サイト閲覧データを記録します。個人を特定するものではなく統計データとして集計されます。",
"GDPR による確認義務に基づきご承認をお願いしております。詳しくは、<a href=\"\/policypolicy\">プライバシーポリシー<\/a>をご参照下さい。",
"アクセス解析を有効にして、お客様の利便性向上にご協力をお願いします。※この設定はプライバシーポリシーからいつでも変更することができます。",
] :
[
"In our website, we will record the website browsing data that using 'Cookie' with Google Analytics. It is a statistical data without identifying personal.",
"We ask for your approval based on the GDPR confirmation obligation. For detail, please refer <a href=\"\/policypolicy\">Privacy Policy<\/a>.",
"Please accept 'Cookie' to enable access analysis and help customers improve their convenience.",
"* This approval setting can be toggled and deleted anytime at Privaci Policy page.",
]
).join("<BR>");
var select = wrapper.appendChild(document.createElement("div"));
var acpBtn = select.appendChild(document.createElement("button"));
var dnyBtn = select.appendChild(document.createElement("button"));
acpBtn.innerHTML = (window.useLang === "ja" ? "同意して Cookie を受け入れる" : "Accept using 'Cookie'");
dnyBtn.innerHTML = (window.useLang === "ja" ? "同意しない" : "Refuse using 'Cookie'");
acpBtn.className = "ga-accept-button";
dnyBtn.className = "ga-deny-button";
acpBtn.type = "button";
dnyBtn.type = "button";
// スマホの時、noticeの高さを制限する
if(document.documentElement.clientWidth <= 640){
var state = true;
var initHeight, timerID, i = 33;
notice.style.transition = "0s";
acceptcss.onload = function(){
initHeight = window.getComputedStyle(notice).height;
console.log(initHeight);
notice.style.height = "50px";
notice.style.transition = "height 0.8s";
notice.style.maskImage = "linear-gradient(0deg, transparent, black 32px)";
notice.style.webkitMaskImage = "linear-gradient(0deg, transparent, black 32px)";
};
var fadeInOut = function(){
if(state){
notice.style.height = initHeight;
--i;
clearInterval(timerID);
timerID = setInterval(function(){
notice.style. maskImage = "linear-gradient(0deg, transparent, black " + i + "px)";
notice.style.webkitMaskImage = "linear-gradient(0deg, transparent, black " + i + "px)";
if(--i < 0){
clearInterval(timerID);
}
}, 25);
} else{
notice.style.height = "50px";
++i;
clearInterval(timerID);
timerID = setInterval(function(){
notice.style. maskImage = "linear-gradient(0deg, transparent, black " + i + "px)";
notice.style.webkitMaskImage = "linear-gradient(0deg, transparent, black " + i + "px)";
if(++i > 32){
clearInterval(timerID);
}
}, 25);
}
state = !state;
};
notice.ontouchend = fadeInOut;
notice.ontouchmove = function($e){ $e.preventDefault(); };
}
// 「同意する」ボタンでCookie受け入れ
acpBtn.onclick = function(){
localStorage.setItem("ganalytics_gdpr_optin", "yes");
// トラッキング設定とgtag.jsの読み込み
gtag("js", new Date());
gtag("config", "UA-*********-*"); // トラッキングID
var gtagjs = document.getElementsByTagName("head")[0].appendChild(document.createElement("script"));
gtagjs.src = "https://www.googletagmanager.com/gtag/js?id=UA-*********-*"; // トラッキングID
// 通知を削除
accept.style.opacity = 0;
accept.style.transition = "0.8s";
setTimeout(function(){
document.body.removeChild(accept);
}, 800);
}
// 「同意しない」ボタンでCookie拒否
dnyBtn.onclick = function(){
localStorage.setItem("ganalytics_gdpr_optin", "no");
// 通知を削除
accept.style.opacity = 0;
accept.style.transition = "0.8s";
setTimeout(function(){
document.body.removeChild(accept);
}, 800);
}
}
});
同意を求める通知のCSS
上記で表示される通知に対する CSS になります。
もちろん好きなスタイルを適応しても大丈夫です。
以下の CSS ではアイコンフォントの Font Awesome 5 Free を使っています。
/* GDPR用のトラッキング同意通知用CSS */
.check-accept-google-analytics{
position : fixed;
bottom : 0;
left : 0;
right : 0;
z-index : 9999;
padding : 10px 5px;
background : linear-gradient(-2deg, #03507D, #048DDC 80%);
font-family : 游ゴシック, 'Yu Gothic', YuGothic, メイリオ, 'Meiryo UI',
'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro','ヒラギノ角ゴ ProN W3',
'Hiragino Kaku Gothic ProN', 'MS Pゴシック', sans-serif;
color : white;
text-align : center;
opacity : 0.95;
}
.check-accept-google-analytics > div{
display : inline-block;
text-align : left;
}
.check-accept-google-analytics > div > div{
text-align : center;
}
.check-accept-google-analytics p{
position : relative;
margin : 5px 10px;
padding-left : 24px;
font-size : 14px;
line-height : 24px;
}
.check-accept-google-analytics p::before{
content : '\f071';
font-family : 'Font Awesome 5 Free';
font-weight : 900;
position : absolute;
top : 0;
left : 0;
}
.check-accept-google-analytics p > a{
color : #E6FF28;
}
.check-accept-google-analytics button{
display : inline-block;
margin : 5px;
padding : 8px 16px;
font-size : 14px;
line-height : 24px;
color : #252525;
border : 1px solid;
border-radius : 26px;
cursor : pointer;
}
.check-accept-google-analytics button::before{
font-family : 'Font Awesome 5 Free';
font-weight : 900;
padding-right : 0.5em;
}
.check-accept-google-analytics button.ga-accept-button{
border-color : green;
background : lime;
}
.check-accept-google-analytics button.ga-deny-button{
border-color : #B83A00;
background : #FF8A54;
}
.check-accept-google-analytics button.ga-accept-button::before{
content : '\f00c';
}
.check-accept-google-analytics button.ga-deny-button::before{
content : '\f00d';
}
@media screen and (max-width: 640px){
.check-accept-google-analytics p{
font-size : 12px;
line-height : 20px;
overflow : hidden;
}
.check-accept-google-analytics button{
padding : 8px 12px;
font-size : 12px;
}
}
ユーザのブラウザ設定言語を取得する方法
上記で、ユーザの言語によって表示を変えるのでユーザの言語設定を検出したいです。
私は PHP で他の用途でも使っているので PHP を使っていますが、もちろん Javascript でも取得できます。
以下は PHP で取得する場合です。グローバルの window.useLang に設定しておきます。
<?php
// ブラウザの言語設定を取得
function get_user_lang(){
// $_SERVER['HTTP_ACCEPT_LANGUAGE'] : 例)'ja,fr;q=0.7,de;q=0.3'
if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
// 言語設定が取得できない場合は'ja'を返す
return 'jp';
}
$lang = array_map(
function($l){
$b = explode(';q=', $l);
return array(
'code' => $b[0],
'quolity' => count($b) > 1 ? (float)$b[1] : 1.0
);
},
explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE'])
);
// 優先度順に並べ替える
usort(
$lang,
function($a, $b){
// 降順
if($a['quolity'] === $b['quolity']){
return 0;
}
return $a['quolity'] < $b['quolity'] ? 1 : -1;
}
);
// 一番優先度の高い言語が日本語なら'ja'を、そうでなければ'en'を返す
if(preg_match('/\Aja/', $lang[0]['code'])){
return 'ja';
} else{
return 'en';
}
}
?>
<script type="text/javascript"><!--
window.useLang = "<?php echo get_user_lang(); ?>";
//--></script>
Javascrip を使う場合は以下のページを参考にして下さい。こちらの方がスッキリ書けます。
・EasyRamble - JavaScript でブラウザの言語設定を取得
// Javascriptで取得する場合は以下のコードを追加
window.useLang = (window.navigator.userLanguage || window.navigator.language || window.navigator.browserLanguage).substr(0, 2) === "ja" ? "ja" : "en";
CookieやGoogle Analyticsの設定をリセットするJavascript
最後に Cookie や Google Analytics の設定をリセットする Javascript になります。
プライバシーポリシーなどに追加するようにして下さい。
// DOMが構築されてからボタンにイベントを設定する
window.addEventListener("DOMContentLoaded", function(){
// 他の処理と併せて記載しても良いです。
setGDPR();
}, false);
// GDPRについての記述を表示して、ボタンにイベントを設定する
var setGDPR = function(){
var GoogleAnalyticsPolicy = document.getElementById("ganalytics");
var deleteCookiesButton = document.getElementById("delete_cookies");
var deleteGtagSetButton = document.getElementById("delete_ganalytics_setting");
var deleteCookiesRun = function(){
for(var i = 0, c = document.cookie.split(";"), n = c.length; i < n; i++){
document.cookie = c[i].replace(/\s*(\S+)=.*/, "$1=delete; max-age=0; domain=設置するサイトのドメイン; path=/");
}
console.log(document.cookie.split(";"));
};
// Javascriptが有効の場合にのみ表示する
if(GoogleAnalyticsPolicy){
GoogleAnalyticsPolicy.style.display = "";
}
// Cookie削除ボタン
if(deleteCookiesButton){
deleteCookiesButton.onclick = deleteCookiesRun;
}
// Analyticsの設定削除ボタン
if(deleteGtagSetButton){
deleteGtagSetButton.onclick = function(){
localStorage.removeItem("ganalytics_gdpr_optin");
// deleteCookiesRun();
location.reload(false);
};
}
};
プライバシーポリシーに記載する時の例文も載せておきます。
もっといい書き方があればぜひ教えて下さい。
<section id="ganalytics" style="display:none">
<h4>アクセス解析の設定初期化とCookie削除</h4>
<p>当サイトでは、Google Analytics によるアクセス解析を行っています。解析には Cookie と呼ばれるお客様の端末 (ブラウザ) に保存される一時データを使用しています。<BR>
Cookie を利用することにより個人を特定するデータを含まないアクセスの履歴 (サイトの内の巡回順序) や回数などのデータを集計し、より良いサイト構築に役立てられます。</p>
<p>ここで、2018年5月25日に施工された個人情報の取り扱いに関する「EU 一般データ保護規則」(<U>G</U>eneral <U>D</U>ata <U>P</U>rotection <U>R</U>egulation、以下「GDPR」) に則り、
Cookie によるデータ収集にはお客様自身の承認が必要となっています。(EU 在住者のみが対象、日本人でもEU 在住者は対象)<BR>
GDPR の保護目的を理解し、当サイトではお客様ご自身の承認ができるまではアクセス解析を実施しておらず、また、いつでも設定を削除できる仕組みを導入しています。</p>
<p>以下のボタンから Cookie の一括削除、アクセス解析の承認・拒否の設定を初期化できます。</p>
<div>
<button type="button" id="delete_cookies">全ての Cookie 削除</button>
<button type="button" id="delete_ganalytics_setting">アクセス解析の承認・否認の設定初期化</button>
</div>
</section>
まとめ
以上、Google Analytics によるアクセス解析を GDPR に対応させる Javascript の紹介でした。
日本のサイトではあまり浸透していない GDPR 法ですが、海外からのアクセスも可能性があれば導入をご検討下さい。
ちなみに、日本のサイトで良く見掛ける「このページを閲覧するには同意したものとみなします」という文言での同意は GDPR 法では完全にアウトです。
ユーザが自発的に同意に対するアクション - 具体的には同意のチェックボックスをクリックしてもらうような - を取る必要があります。
従って、はじめから同意のチェックボックスにチェックが入っている場合もアウトですのでご注意下さい。