DjangoでGoogle Analyticsを特定の環境でのみ有効にする

## 概要
Google Analyticsをサイトへ実装した場合、特段の設定を行わなければLocalやStaging環境へのアクセスもトラッキングしてしまう。これを防ぐためDjango側でProduction環境以外ではGoogle Analytcsが動作しないようにしなければならない。

この記事ではDjangoの機能 「Context Processor」を使い特定の環境でのみGoogle Analyticsを有効にする方法について解説する。

## I Context Processorとは
簡単に説明すると、全てのtemplateへkey: Valueペアの値を差し込むことができる機能である。

Context Processorのメソッドは必ずrequestを引数とし受け取り, dictionaryを返す。

例えば以下のようなContext Prosessorのメソッドを定義すると、全てのtemplateから’key_accessible_from_all_templates’や'is_ham_included'のキーの値を取得できるようになる。


```python:context_processors.py
from django.conf import settings

# Example1
def hame_spam_context_processor(request):
    return {'key_accessible_from_all_templates': 'add any value here' }
    
# Example2
def sample_bool_context_processor(request):
  return {'is_ham_included': true }
  
```


```html:rendering_django_template_html
<!-- テンプレートからのアクセス例 -->

<!--# Example1  -->
<!--'add any value here’が出力される-->
{{ key_accessible_from_all_templates }} 

<!--# Example2 -->
<!--bool等で条件分岐を行うことも可能-->
{% is_ham_included %} 
    <p>Ham is included</p>
{% endif %}
```


## II Context Processorの実装
TemplateへGoogle Analyticsを有効にするか否かのFlagを送るためのContext Processorを実装する

### 1. ソースファイルを追加
ファイルの配置場所はどこでも良いが、のちにsettings.pyでファイルの場所をしていうする必要がある。
今回のTutorialではsettings.py等がデフォルトで置いてあるプロジェクトフォルダ配下に配置する。

- mysite
  - settings.py
  - wsgi.py
  - views.py
  - context_processors.py <- これを追加


### 2. コードを追加
google analyticsを有効にするかのflagを返すContext Processorの
メソッドを１つ定義する。

```python:context_processors.py

from django.conf import settings

# メソッド名はなんでも良いが、後にsettings.pyでこのファイルの置き場と共に指定する必要がある。
def activate_google_analytics(request): 

    # 'activate_google_analytics'のkeyの値が全てのtemplateからアクセス可能になる。
    #
    # この例ではsettings.pyの内部からTrue, Falseを取ってきているが、bool値の取得
    # 方法はなんでも良い。
    return {'activate_google_analytics': settings.ACTIVATE_GOOGLE_ANALYTICS }
```


### 2. settings.pyへ登録
Context Processorを有効にするにはsettings.pyで登録が必要である。

settings.pyのTEMPLATESの部分へ先ほど作成したContext Processorのファイルとファイル内のメソッドを名を合わせたpathを設定する。


```python:settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'mysite.context_processors.activate_google_analytics', # <- この行を追加
            ],
        },
    },
]

# mysite.context_processorsまでの部分がContext Processorを記載したファイルの場所
# activate_google_analyticsがファイル内に定義しているメソッド名
```


### 3. Templateからのアクセス
Context Processorを定義して全てのtemplateへその値が渡す準備ができた後は、TemplateからContext Processor定義の値を受け取らなければならない。

base.htmlでgoogle analyticsを{% include %}を使って差し込んでる仮定で実装方法を解説する。
他の方法でgoogle analyticsを差し込んでいても、この方法を応用して簡単に実装ができると思う。

#### Context Processorの値を使う前

```html:base.py
<!DOCTYPE html>
<html>

<head>
    <!-- google analyticsはhead内の一番上に来なければいけない by Google公式doc -->
    {% include 'snippets/google_analytics.html' %}
    
    <!--titleやらcssやらあれこれ以下に入る-->

</head>


<body>
  <!--body部分省略-->
</body>

</html>
```

#### Context Processorの値を差し込んだ後
Context Processorの値を使ってif分岐を行い、google analyticsのsnippetの差し込みをコントロールしている。一部のコメントは削除。

```html:base.py
<!DOCTYPE html>
<html>

<head>
    {% if activate_google_analytics %}<!--追加行-->
      {% include 'snippets/google_analytics.html' %}
    {% endif %}<!--追加行-->
    

</head>


<body>
  <!--body部分省略-->
</body>

</html>
```




## III google analyticsを有効にするか否かのフラグ制御
Context Processorそのものはgoogle analyticsを表示するかどうかのflagを他の場所から受けっとって返しているにすぎない。そのため実際にこのflagを制御する機能を実装する必要がある。

今回の例ではsettings.pyへ環境変数を渡すことで制御する方法で実装する。

繰り返すが最終的にContext Processorでflagの値(bool)へアクセスできればどこでどのような方法で実装しても問題ない。



### Settings.pyでflagを定義
ACTIVATE_GOOGLE_ANALYTICSという環境変数が渡されている場合のみACTIVATE_GOOGLE_ANALYTICSへTrueが入るようにする。

ACTIVATE_GOOGLE_ANALYTICSはContext Processorからアクセスされ、その値はContext Processorを通じて最終的に全てののtemplateへグローバルに渡される。

### コード実装例
```python:settings.py
if 'ACTIVATE_GOOGLE_ANALYTICS' in os.environ:
    ACTIVATE_GOOGLE_ANALYTICS = True
else:
    ACTIVATE_GOOGLE_ANALYTICS = False


```