更新履歴

  • 2022-08-07 : GTMを利用する場合に追加で設定が必要だったため加筆修正
  • 2022-07-10 : ページ公開

はじめに

ウェブサイトやアプリが取得するデータと利用目的を、ユーザーに説明して、同意を得るためのツール"同意管理プラットフォーム(CMP:Consent Management Platform)"が、注目を集めています。

有料のクラウドサービス、無料のツールなどいくつかありますが、本記事では、無料のJavaScriptプラグイン Cookie Consent と、実装方法をご紹介します。

多言語対応や、GoogleタグマネージャーでGoogleアナリティクスを利用する場合の実装方法もご紹介します。

Cookie Consentとは

Cookie Consent は、無料の、GDPRに対応したJavaScriptプラグインです。

以下からダウンロードできます。

orestbida/cookieconsent: Simple cross-browser cookie-consent plugin written in vanilla js

大まかな実装手順

以下の通りです。

  1. プラグインのJavaScriptを読み込む
  2. プラグインのCSSを読み込む
  3. プラグインの設定コードを記述する
  4. 利用している分析ツール等の<script>タグを編集する

Googleタグマネージャーを利用している場合の注意点

Googleタグマネージャー(GTM)を利用している場合は、GTMの読み込みコードより先に Cookie Consentを発火させる必要があります。

プラグインのJavaScriptとCSSを読み込む

以下のように、CSSとJSを読み込みます。

JSの場所はbodyタグ内でもheadタグ内でも大丈夫です。

<html>
    <head>
        <!-- head content -->
        <!-- Deferred CSS loading (recommended) -->
        <link rel="stylesheet" href="<path-to-cookieconsent.css>" media="print" onload="this.media='all'">
    </head>
    <body>
        <!-- body content -->
        <script defer src="<path-to-cookieconsent.js>"></script>
    </body>
</html>

CSSとJSはCDNからも読み込みができます。

# CDN links
https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@v2.8.2/dist/cookieconsent.js
https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@v2.8.2/dist/cookieconsent.css

GTMを利用する場合は、以下のような順番になります。 GTMのscriptタグの属性は後述します。

<!-- プラグインのJS -->
<script defer src="../../src/cookieconsent.js"></script>

<!-- プラグインの設定JS -->
<script defer src="cookieconsent-init.js"></script>

<!-- GTMのタグ -->
<script type="text/plain" data-cookiecategory="analytics">
    // Google Tag Manager (configured with GA internally)
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>

プラグインの設定コードを記述する - 基本的な書き方

次に、プラグインの設定コードを用意します。

以下が基本的な書き方です。

詳しくはコード内のコメントをご覧ください。

// Cookie Consent プラグインの取得
var cc = initCookieConsent();

// プラグインを設定した内容で動作させる
cc.run({
    current_lang : 'en',  // 言語設定。多言語対応については後述します。
    autoclear_cookies : true,  // 特定のカテゴリのCookieがオプトアウトされたらクッキーを自動的に削除する。 default: false
    cookie_name: 'cc_cookie_demo1', // このプラグインのCookieの名前。 default: 'cc_cookie'
    cookie_expiration : 365,  // このプラグインのCookieの有効期限。 default: 182
    page_scripts: true,  // ここで紹介するようにscriptタグの属性値でプラグインを設定する場合は trueにする。  default: false

    // auto_language: null,  // 言語の自動設定。後述します。  default: null; could also be 'browser' or 'document'
    // autorun: true,  // default: true
    // delay: 0,  // default: 0
    // force_consent: false,
    // hide_from_bots: false,                   // default: false
    // remove_cookie_tables: false              // default: false
    // cookie_domain: location.hostname,        // default: current domain
    // cookie_path: "/",                        // default: root
    // cookie_same_site: "Lax",
    // use_rfc_cookie: false,                   // default: false
    // revision: 0,                             // default: 0

    // レイアウトの設定。ここにあるオプションを変更することでレイアウトが変更できます。
    gui_options: {
        consent_modal: {
            layout: 'box',                      // box,cloud,bar
            position: 'bottom right',           // bottom,middle,top + left,right,center
            transition: 'slide'                 // zoom,slide
        },
        settings_modal: {
            layout: 'box',                      // box,bar
            // position: 'left',                // right,left (available only if bar layout selected)
            transition: 'slide'                 // zoom,slide
        }
    },

    // 初回動作時に実行したいコード
    onFirstAction: function(){
        console.log('onFirstAction fired');
    },

    // Cookieが同意された際に実行したいコード
    onAccept: function (cookie) {
        console.log('onAccept fired ...');
    },

    // Cookie同意内容が変更された際に実行したいコード
    onChange: function (cookie, changed_preferences) {
        console.log('onChange fired ...');
    },

    // 言語別の設定
    languages: {
        'en': {
            // モーダルのテキスト
            consent_modal: {
                title: ' We use cookies! ',
                description: 'Hi, this website uses essential cookies to ensure its proper operation and tracking cookies to understand how you interact with it. The latter will be set only after consent. <button type="button" data-cc="c-settings" class="cc-link">Let me choose</button>',
                primary_btn: {
                    text: 'Accept all',
                    role: 'accept_all'              // 'accept_selected' or 'accept_all'
                },
                secondary_btn: {
                    text: 'Reject all',
                    role: 'accept_necessary'        // 'settings' or 'accept_necessary'
                }
            },

            // Cookieの詳細設定のテキスト
            settings_modal: {
                title: `Cookie Settigs`,
                save_settings_btn: 'Save settings',
                accept_all_btn: 'Accept all',
                reject_all_btn: 'Reject all',
                close_btn_label: 'Close',

                // それぞれのクッキーの説明を記載するテーブルの項目名
                cookie_table_headers: [
                    {col1: 'Name'},
                    {col2: 'Domain'},
                    {col3: 'Expiration'},
                    {col4: 'Description'}
                ],
                blocks: [
                    {
                        title: 'Cookie usage',
                        description: 'I use cookies to ensure the basic functionalities of the website and to enhance your online experience. You can choose for each category to opt-in/out whenever you want. For more details relative to cookies and other sensitive data, please read the full <a href="#" class="cc-link">privacy policy</a>.'
                    }, {
                        title: 'Strictly necessary cookies',
                        description: 'These cookies are essential for the proper functioning of my website. Without these cookies, the website would not work properly',
                        toggle: {
                            value: 'necessary',  // Cookieのカテゴリ名。ここで定義したカテゴリ名を、scriptタグのdata-cookiecategory属性に指定します。
                            enabled: true,
                            readonly: true          // cookie categories with readonly=true are all treated as "necessary cookies"
                        }
                    }, {
                        title: 'Performance and Analytics cookies',
                        description: 'These cookies allow the website to remember the choices you have made in the past',
                        toggle: {
                            value: 'analytics',  // Cookieのカテゴリ名。ここで定義したカテゴリ名を、scriptタグのdata-cookiecategory属性に指定します。
                            enabled: false,
                            readonly: false
                        },
                        // 上述したテーブルの項目名に合わせて、テキストを記載します。
                        // この cookie_table そのものを省略すれば、各Cookieの説明も省略できます。
                        cookie_table: [
                            {
                                col1: '^_ga',
                                col2: 'google.com',
                                col3: '2 years',
                                col4: 'description ...',
                                is_regex: true  // 正規表現を有効にするかどうかの設定
                            },
                            {
                                col1: '_gid',
                                col2: 'google.com',
                                col3: '1 day',
                                col4: 'description ...',
                            }
                        ]
                    }, {
                        title: 'Advertisement and Targeting cookies',
                        description: 'These cookies collect information about how you use the website, which pages you visited and which links you clicked on. All of the data is anonymized and cannot be used to identify you',
                        toggle: {
                            value: 'targeting',  // Cookieのカテゴリ名。ここで定義したカテゴリ名を、scriptタグのdata-cookiecategory属性に指定します。
                            enabled: false,
                            readonly: false
                        }
                    }, {
                        title: 'More information',
                        description: 'For any queries in relation to my policy on cookies and your choices, please <a class="cc-link" href="https://orestbida.com/contact">contact me</a>.',
                    }
                ]
            }
        }
    }

});

利用している分析ツール等の<script>タグを編集する

設定コードに記述した settings_modal > blocks > toggle > value の値に応じて、分析ツール等で利用する外部スクリプトのタグの属性値を type="text/plain" data-cookiecategory="{category name}"のように編集します。

以下のサンプルを参考にしてください。

<script type="text/plain" data-cookiecategory="analytics" src="analytics.js" defer></script>

<script type="text/plain" data-cookiecategory="ads">
    console.log('"ads" category accepted');
</script>

これで設定は完了です。

GTMでGoogleアナリティクスを利用する場合の書き方

GTMを利用してGoogleアナリティクスを利用する場合、GTMの管理画面ではカスタムHTMLではなく、ユニバーサルアナリティクスGA4など、計測方法にあったタグの種類を選択します。

カスタムHTMLを利用してアナリティクスの計測タグを入力すると、以下のような警告が表示されます。

Any gtag commands in custom HTML may not work as intended due to how the data layer processes information. カスタムHTML内のgtagコマンドは、データレイヤーの処理方法によって、意図したとおりに動作しない場合があります。

つまり、scriptタグの属性値を直接編集することができません。

その場合は、少し工夫が必要です。

まず、前述したコードと同じですが、Cookie Consentの後にGTMが読み込まれるようにする必要があります。

そして、GTMを読み込むscriptタグの属性値にCookie Consentのための属性値を記述します。

<!-- プラグインのJS -->
<script defer src="../../src/cookieconsent.js"></script>

<!-- プラグインの設定JS -->
<script defer src="cookieconsent-init.js"></script>

<!-- GTMのタグ -->
<script type="text/plain" data-cookiecategory="analytics">
    // Google Tag Manager (configured with GA internally)
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>

次に、Cookie Consentの設定コードで、Cookie Consentanalyticsのカテゴリで同意が得られれば、GoogleアナリティクスのCookieにデータが保存されるように記述します。

onChange: function(cookie, changed_preferences) {
    if (cc.allowedCategory('analytics')) {
        gtag('consent', 'update', {
            'analytics_storage': 'granted'
        });
    } else {
        gtag('consent', 'update', {
            'analytics_storage': 'denied'
        });
    }
}

onChangeは、cookie同意の設定が変わった際に発火するコールバック関数です。

以下を参考にしてください。

Available callbacks - orestbida/cookieconsent

allowedCategoryについてはこちらのセクションが参考になります。

API methods - orestbida/cookieconsent

analytics_storageはGoogleタグマネージャーが同意に基づき管理するデータの1つで、分析のためのCookieを有効にするかどうかの同意の1つです。

他にも、広告関連のCookieを保存する同意種別としてad_storageがあります。

詳しくは、こちらの記事が参考になります。

同意設定を管理する(ウェブ)  |  Tags  |  Google Developers

Manage consent settings (web)  |  Tags  |  Google Developers

同意の設定 - タグ マネージャー ヘルプ

Consent configuration - Tag Manager Help

2022-08-07 追記
上記のonChangeのコールバック関数内の記述では、Cookieがきちんとセットされないようでした。

よって、GTMの計測タグの下部に、以下のコードを記述し、この問題を解消しました。

<!--- enable analytics when "analytics" category is selected --->
<script type="text/plain" data-cookiecategory="analytics">
    gtag('consent', 'update', {
        'analytics_storage': 'granted'
    });
</script>

Cookie ConsentへのGTMの同意モードの導入は、以下のIssueとして挙がっていますが、現状は、上記のコードで対応するのが良いとのことでした。
(onChangeメソッドの方法も記載されているのですが、私の環境では何故か動作しませんでした)

Add native support of GTM's Consent Mode (GCM) · Issue #110 · orestbida/cookieconsent · GitHub

GTMで設定するタグのトリガータイプ

GTMで管理している各種タグのトリガータイプは、「初期化(Initialization)」ではなく「ページビュー(Page View)」にします。

「初期化(Initialization)」だと、Cookie ConsentのバナーでCookieの利用に同意した場合でも、タグがきちんと発火しませんでした。

多言語設定

まず、複数言語を設定するには、以下のブロックを言語別に用意します。

languages: {
    'en': {}
}

次に、アクセスしているページに応じて、表示させる言語を設定します。

明示的に変更したい場合は、current_langに、表示させたい言語をセットします。

環境に応じて言語を変更したい場合は、current_langを削除し、auto_languageを適用します。

auto_languageのオプションは以下の2つです。

auto_language: 'browser',  // ブラウザの設定に応じて変更されます
auto_language: 'document', // <html lang="..."> に応じて変更されます

今回の記事は以上です。