uktrade/directory-components

View on GitHub
demo/templates/demo/google-tag-manager.html

Summary

Maintainability
Test Coverage
{% extends 'demo/base.html' %}
{% load breadcrumbs ga360_data card from directory_components %}
{% load static %}
{% load code from demo_tags %}

{% block head_js_ga360 %}
    {{ block.super }}
    <script>dit.tagging.base.init(true)</script>
{% endblock %}

{% block content %}

{% static 'images/card_image01.jpg' as card_image01 %}

<div class="container">
    {% breadcrumbs 'Google Tag Manager' %}
        <a href="/">Home</a>
    {% endbreadcrumbs %}
</div>

<section>
    <div class="container">
        <h1 class="heading-xlarge">Google Tag Manager</h1>
    </div>
</section>

<section>
    <div class="container">
        <h2 class="heading-large">Introduction</h2>

        <h3 class="heading-medium">TL;DR</h3>
        <p class="width-two-thirds">
            As long as your page satisfies the following criteria, all basic analytics should be taken care of without
            you having to do anything!
        </p>

        <ol class="list list-bullet width-two-thirds">
            <li>Your template extends <code>base.html</code></li>
            <li>Your view extends the <code>GA360Mixin</code></li>
            <li>Your app uses the (correctly configured) <code>analytics</code> context processor</li>
        </ol>

        <p class="width-two-thirds">
            If you don't want to extend the base template, or if you'd like finer grained control over how things are
            tagged on your page, then keep reading to find out the details!
        </p>

        <h3 class="heading-medium">Purpose</h3>
        <p class="width-two-thirds">
            Google Analytics on its own is able to track a lot of data such as the number of page hits,
            information about how users arrive on our sites etc.
        </p>

        <p class="width-two-thirds">
            For more detailed tracking of how users interact with our sites, we use Google Tag Manager (GTM) to record
            details such as what pages a user visits, if they are signed in and what elements on the page they
            interact with.
        </p>

        <p class="width-two-thirds">
            This page details our GTM setup, and the tools we have created to make this tracking simple.
        </p>

        <h3 class="heading-medium">Explaining the DataLayer</h3>
        <p class="width-two-thirds">
            Whenever something happens on the page (eg the page is loaded, or the user clicks on a button), an event
            is raised to record what happened. These events are then sent to Google Analytics, where they can be used
            to build up a picture of how the site is being used.
        </p>
        <p class="width-two-thirds">
            It is possible to post these events directly to Google Analytics, but instead we prefer to push our events
            to a global JS variable called the 'dataLayer'. The 'dataLayer' is managed by the GTM scripts, and will
            gather up various events that occur, before sending them off to GTM all in one go. One advantage of this
            approach is to significantly reduce the number of calls that we need to make to GTM.
        </p>
    </div>
</section>

<section>
    <div class="container">
        <h2 class="heading-large">Page Level Tracking</h2>
        <p class="width-two-thirds">
            We'd like to record data about every page hit.
            To do this, we have a set of tools to manage pushing an event to the dataLayer on every page load.
        </p>

        <h3 class="heading-medium">Setup</h3>
        <p class="width-two-thirds">
            In most cases this will be handled for you via the <code>base.html</code> file.
            To configure this correctly, add the provided <code>analytics</code> context processor to your project,
            and add the following variables to your settings file:
        </p>
        <ul class="list list-bullet">
            <li><code>GOOGLE_TAG_MANAGER_ID</code></li>
            <li><code>GOOGLE_TAG_MANAGER_ENV</code></li>
            <li><code>UTM_COOKIE_DOMAIN</code></li>
        </ul>

        <p class="width-two-thirds">
            With these set, a script will be added to the page to setup GTM and the dataLayer.
            A fallback will also be added to ensure that this will continue to work even without Javascript enabled.
        </p>

        <h3 class="heading-medium">Adding Data to Response</h3>
        <p class="width-two-thirds">
            This is as simple as extending the provided <code>GA360Mixin</code> in your view.
        </p>

        {% code 'python' %}
            class MyView(GA360Mixin, BaseView):
                # stuff
                # more stuff
        {% endcode %}

        <p class="width-two-thirds">
            Once added, the following object will be added to your context and therefore be available in your templates.
        </p>

        {% code 'python' %}
            ga360 = {
                'page_id': '{page_type_from_cms}',
                'business_unit': '{root_app_from_cms}', # eg 'invest/trade'
                'site_section': '{site_section_from_cms}', # eg 'industries/guides'
                'site_subsection': '{site_subsection_from_cms}', # eg 'contact/listingPage'
                'site_language': '{language_of_page}',
                'login_status': '{is_the_user_signed_in}',
                'user_id': '{sso_user.id}'
            }
        {% endcode %}


        <h3 class="heading-medium">Ensuring Response Contains Data</h3>
        <p class="width-two-thirds">
            Analytics data is hugely important to us. We would therefore like to ensure that all of our views set the
            required fields. To make it impossible to accidentally omit this data, we have provided the
            <code>CheckGA360</code> middleware.
            To use it, simply add this class to your list of middleware classes.
        </p>

        <p class="width-two-thirds">
            Once added, all 2xx responses MUST either include the ga360 object in it's context, or be explicitly flagged
            as not requiring analytics.
        </p>

        <p class="width-two-thirds">
            To mark a view as not requiring analytics, apply the <code>skip_ga360</code> decorator to the view function.
            The easiest way to do this is in <code>urls.py</code>
        </p>

        {% code 'python' %}
            url(
                r"^some/path/$",
                skip_ga360(View.as_view()),
                name='some-path'
            )
        {% endcode %}


        <h3 class="heading-medium">Send Data to GTM</h3>

        <p class="width-two-thirds">
            The final step is to send this page level data to GTM. Any template that extends the <code>base.html</code>
            template will automatically handle this for you.
        </p>
    </div>
</section>

<section id="user-interaction-tracking">
    <div class="container">
        <h2 class="heading-large">User Interaction Tracking</h2>
        <p class="width-two-thirds">
            We'd also like to record how our users interact with our site. For example, we'd like to know which links
            people click on the most, which videos people watch, or which forms people fill in.
        </p>
        <p class="width-two-thirds">
            There are too many of these kinds of interactions to manually tag each element on the page. Instead, we
            have created a base file that will automatically tag a few of the most common types of elements to track.
        </p>
        <p class="width-two-thirds">
            The concept is to apply some basic logic which will roughly track most of the elements on the page. It is
            unlikely to be perfect, but should be a good place from which to start. For elements where we need a little
            more detail, or wish to track extra interactions, its easy to add to explicit overrides to improve the
            tracking.
        </p>

        <h3 class="heading-medium">Setup</h3>

        <p class="width-two-thirds">
            To get the base level tracking, simply load the <code>dit.tracking.js</code> file into the page sources,
            and then call it's <code>init()</code>function.
        </p>

        {% code 'html' %}
            <script src="{% static 'directory_components/js/dit.tagging.js' %}"></script>
            <script>
                dit.tagging.base.init();
            </script>
        {% endcode %}


        <p class="width-two-thirds">
            As normal, if you are extending the <code>base.html</code> template then this will already have been done
            for you.
        </p>

        <h3 class="heading-medium">Event Details</h3>
        <p class="width-two-thirds">
            Every interaction event will contain the following fields.
        </p>

        {% code 'python' %}
            {
                'event': 'gaEvent',  # always has this value - required for our analytics pipeline.
                'action': '',  # the type of interaction taken by the user. eg. 'clickLink', 'submitForm'
                'type': '',  # what kind of object the user interacted with. eg 'cta', 'searchForm'
                'element': '',  # the region of the page where the link was found. eg 'hero', 'industries'
                'value': '',  # data specific to this interaction. eg the link text.
            }
        {% endcode %}

        <p class="width-two-thirds">
            The code will attempt to populate these fields with sensible options, but you are free to overwrite these
            values by setting attributes on the corresponding HTML elements. To help with this, we provide the
            'ga360_data' tag.
        </p>

        {% code 'django' %}
            {% ga360_data '{target}' action='{action}' type='{type}' element='{element}' value='{value}' %}
                # HTML Content
            {% end_ga360_data %}
        {% endcode %}

        <p class="width-two-thirds">
            This tag will overwrite the corresponding fields of any element matching the 'target' selector.
            You must provide a target, but all other fields are optional.
        </p>

        <h3 class="heading-medium">Links</h3>
        <p class="width-two-thirds">
            The code will attempt to add tagging for all <code>&lt;a&gt;</code> tags on the page.
            All clicks (or enter key presses) on a tagged link will trigger an event to sent to the data layer.
        </p>

        <p class="width-two-thirds">By default, the fields will be populated as follows.</p>

        <table class="margin-bottom-30">
            <thead><tr><td class="width-sixth">Key</td><td class="width-quarter">Default Value</td><td>Comment</td></tr></thead>
            <tr><td>Action</td><td>'clickLink'</td><td></td></tr>
            <tr><td>Type</td><td>'pageLink' / 'card' / 'cta'</td><td>Inferred as described in the sections below</td></tr>
            <tr><td>Element</td><td>Inferred from parents</td><td>Scans itself and ancestors for an element with a 'data-ga-section'. Falls back to an element with an 'id' attribute. Else an empty string.</td></tr>
            <tr><td>Value</td><td>Inferred from contents</td><td>The link text if it exists. Otherwise it scans the descendent HTML looking for text that is likely to be a title.</td></tr>
            <tr><td>Destination</td><td>The href of the link</td><td></td></tr>
        </table>

        <h4 class="heading-small">Cards</h4>
        <p class="width-two-thirds">Any link which is a <a href="{% url 'cards' %}">card</a>. Determined by testing the css class of the link for relevant terms.</p>
        <h4 class="heading-small">CTAs</h4>
        <p class="width-two-thirds">Any link which is a <a href="{% url 'message-boxes' %}">CTA Box</a> or a <a href="{% url 'buttons' %}">Button</a>. Determined by testing the css class of the link for relevant terms.</p>

        <h4 class="heading-small">Standard Links</h4>
        <p class="width-two-thirds">Any link that isn't a Card or a CTA.</p>

        <h3 class="heading-medium">Forms</h3>
        <p class="width-two-thirds">
            The code will attempt to add tagging for all <code>&lt;form&gt;</code> tags on the page.
            All form submissions will trigger an event to sent to the data layer.
        </p>

        <p class="width-two-thirds">By default, the fields will be populated as follows.</p>

        <table class="margin-bottom-30">
            <thead><tr><td class="width-sixth">Key</td><td class="width-quarter">Default Value</td><td>Comment</td></tr></thead>
            <tr><td>Action</td><td>'submit'</td><td></td></tr>
            <tr><td>Type</td><td>'form'</td><td></td></tr>
            <tr><td>Element</td><td>Inferred from parents</td><td>Scans itself and ancestors for an element with a 'data-ga-section'. Falls back to an element with an 'id' attribute. Else an empty string.</td></tr>
            <tr><td>Value</td><td>The form's action</td><td></td></tr>
            <tr><td>Data</td><td>$(theForm).serialize()</td><td>Only set if the form has the <code>data-ga-include-form-data</code> attribute set to "True".</td></tr>
        </table>

        <h3 class="heading-medium">Videos</h3>
        <p class="width-two-thirds">
            The code will attempt to add tagging for all <code>&lt;video&gt;</code> tags on the page.
            All play, pause or complete video actions will trigger an event to sent to the data layer.
        </p>

        <p class="width-two-thirds">By default, the fields will be populated as follows.</p>

        <table class="margin-bottom-30">
            <thead><tr><td class="width-sixth">Key</td><td class="width-quarter">Default Value</td><td>Comment</td></tr></thead>
            <tr><td>Action</td><td>'play/pause/ended'</td><td></td></tr>
            <tr><td>Type</td><td>'video'</td><td></td></tr>
            <tr><td>Element</td><td>Inferred from parents</td><td>Scans itself and ancestors for an element with a 'data-ga-section'. Falls back to an element with an 'id' attribute. Else an empty string.</td></tr>
            <tr><td>Value</td><td>The video's source</td><td></td></tr>
        </table>

        <h3 class="heading-medium">Examples</h3>
        <p class="width-two-thirds">
            Try out the following interactions. View the triggered events in your console.
            (Hint, open the links in a new tab to view link events)
        </p>

        <h4 class="heading-small">Plain Link</h4>
        {% code 'html' %}
            <a href="#">Click Me</a>
        {% endcode %}

        <a href="#">Click Me</a>

        <h4 class="heading-small">Link within a section</h4>
        {% code 'html' %}
            <div data-ga-section="test-section">
                <a href="#">Click Me</a>
            </div>
        {% endcode %}

        <div data-ga-section="test-section">
            <a href="#">Click Me</a>
        </div>

        <h4 class="heading-small">Link With Overwrites</h4>
        {% code 'django' %}
            {% ga360_data 'a' element="test-section" value="Special Click" %}
                <a href="#">Click Me</a>
            {% end_ga360_data %}
        {% endcode %}

        {% ga360_data 'a' element="test-section" value="Special Click" %}
            <a href="#">Click Me</a>
        {% end_ga360_data %}

        <h4 class="heading-small">CTA</h4>
        {% code 'html' %}
            <a class="button">
                <span>Click Me</span>
            </a>
        {% endcode %}


        <a class="button">
            <span>Click Me</span>
        </a>

        <h4 class="heading-small">Card</h4>
        {% code 'django' %}
            <div class="column-half">
                {% card img_src=card_image01 img_alt='Card image description' url='#' title='Card title' description='Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' %}
            </div>
        {% endcode %}


        <div class="flex-grid">
            <div class="column-third">
                {% card img_src=card_image01 img_alt='Card image description' url='#' title='Card title' description='Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' %}
            </div>
        </div>

        <h4 class="heading-small">Form</h4>
        {% code 'django' %}
            {% ga360_data "form" include_form_data="True" %}
                <form action="/" class="form-group">
                    <label class="form-label">
                        Name
                        <input type="text" class="form-control">
                    </label>
                    <button type="submit" class="button margin-top-30">Submit</button>
                </form>
            {% end_ga360_data %}
        {% endcode %}


        {% ga360_data "form" include_form_data="True" %}
            <form action="#" class="form-group">
                <label class="form-label">
                    Name
                    <input type="text" class="form-control" name="name">
                </label>
                <button type="submit" class="button margin-top-30">Submit</button>
            </form>
        {% end_ga360_data %}
    </div>
</section>

{% endblock %}