How To: Google Tag Manager in Shopify checkout

2 minute read

If you plan on injecting script tags in your Shopify theme, then I strongly recommend to use Google Tag Manager. This way, a change or a new script won’t require changes in your theme files. All this can be done in Google Tag Manager.

As you add your new tags to GTM, sooner or later you will find that you might need order details to be sent to various tags. This information is not available in Shopify by default, but it’s possible to add it.

As you might noticed, you can’t change the checkout template. The template file is only available for Shopify PLUS accounts. And, it’s not enabled by default. To enable the checkout.liquid, you might need to contact Shopify support. It’s not strictly required to do this as in most of the times, you only need to track conversions, rather than any event during the checkout.

To track conversions and make all order details available in the dataLayer, you don’t have to edit any template. Once the Google Tag Manager script is in your theme.liquid, you need to go to Settings > Checkout > Additional Scripts in the admin and paste the following code to the textarea:

window.dataLayer = window.dataLayer || [];

function transactionComplete() {
    var totalDiscount = 0;

    {% for discount in order.discounts %}
        totalDiscount += {{ discount.savings | times: 0.01 }};
    {% endfor %}
    return dataLayer.push({
        event : 'transactionComplete',
        checkout: {
            'transactionId': '{{order.order_number}}',
            'transactionTotal': {{total_price | times: 0.01}},
            'transactionRevenue': {{subtotal_price | times: 0.01}},
            'transactionCurrency': 'USD',
            'transactionShipping': {{shipping_price | times: 0.01}},
            'transactionTax': {{tax_price | times: 0.01}},
            'transactionDiscount': totalDiscount,
            'transactionProducts': [
            {% for line_item in line_items %}
                'id': '{{line_item.product_id}}',
                'sku': '{{line_item.sku}}',
                'name': '{{line_item.title}}',
                'category': '{{line_item.type}}',
                'price': {{line_item.line_price | times: 0.01}},
                'quantity': {{line_item.quantity}}
            {% endfor %}]

function orderStatus() {
    return dataLayer.push({
        event : 'orderStatus',
        customer : {
            id: '{{}}',
            name: "{{ }}",
            firstName: "{{ customer.first_name }}",
            lastName: "{{ customer.last_name }}",
            email: "{{ }}",
            phone: "{{ }}",
            address: {  // uses the default address
                street: "{{ customer.default_address.street }}",
                city: "{{ }}",
                state: "{{ customer.default_address.province }}",
                stateCode: "{{ billing_address.province_code }}",
                postalCode: "{{ }}",
                country: "{{ }}",
                countryCode: "{{ customer.default_address.country_code }}"
            totalSpent: "{{ customer.total_spent }}",
            allOrdersCount: "{{ customer.orders_count }}",
            allOrderIds: [{% for order in customer.orders %}"{{ }}",{% endfor %}],
            tags: [{% for tag in customer.tags %} "{{ tag }}", {% endfor %}]

{% if first_time_accessed %}
{% else %}
{% endif %}

Credit to toddheslin for the original work.

I modified the script to remove the function wrapper from around the checkout variable. To add these values to a GTM variable, choose variable type “dataLayer” and key in the variable name from the JSON array, for example: checkout.transactionRevenue will be the order subtotal.

Now the new data is ready to use in tags. The trigger should be an event, rather than Page View. The event name as it’s sent from the code above is “transactionComplete”. On page view, the dataLayer is not populated because it’s not running javascripts.