blog.1.image
Design
July 21, 2020

How to track ezoic Ads impressions with Google Tag Manager

by Justus

The company called ezoic tries to maximize display ad revenue using automated optimization while keeping things simple for publishers to a point where you can add a bunch of ads to your site with just a simple code snippet or an easy installation of a Wordpress plugin.
I don’t work with them myself but I have gotten several first-hand reports from friends of very significant increases in ad revenue compared to a similar integration of Google AdSense with very little migration effort. You can find public results of such a comparison over at DevAnswers.co.

You can check out an example for an ezoic Ads implementation at goodcalculators.com (which I am not affiliated with):

An example website using ezoic Ads

Lots of other sites using ezoic ads on BuiltWith.com

What we want to track

  • How often ads are displayed
  • Which formats these ads have (width x height in pixels)

Both pieces of information are not static and can vary with each individual page view due to Ezoic’s approach to test different ad locations and formats to maximize your click-through-rate and thus revenue.

We also want to track auto-refreshed ad impressions: When a user remains on a page for a while, the ads are reloaded which counts as a new impression.

Unfortunately there’s no way to track clicks on the ads with a JavaScript based method because the ads are wrapped in iframes which isolates them from the rest of the page and Google Tag Manager will not register any click events inside those iframes.

Of course ezoic offers some reporting in their backend but – as usual – having data about your ads in the same place as all your other behavioral analytics (like Google Analytics) is a valuable addition. Below you’ll find the solution for tracking the impressions of your ezoic Ads together with

  • The width of the ad
  • The height of the ad
  • The name of the placement (the position in which the ad was displayed)

A dataLayer event for such an impression will look like this:

{
  "event": "ezoic.adimpression",
  "ezoic": {
    "adimpression": {
      "width": 970,
      "height": 90,
      "placement": "goodcalculators_com-medrectangle-2"
    }
  }
}
dataLayer events for ezoic Ads impressions

Let’s get into how you can achieve this:

Requirements

Your ezoic Ads implementation has to be set up in a way that makes sure the ad containers are already in the HTML provided directly from the server, otherwise the script won’t be able to identify which elements are ads. You can check if you have those ad containers ready by checking your source code and searching for data-ez-name which is an HTML attribute they have by default:

An ezoic Ad container

The script

Implement the following script in your Google Tag Manager container as a Custom HTML tag and add a trigger to make it load as early as possible, but definitely before your ezoic Ads are loaded.

<script>
(function(){
    var ads = document.querySelectorAll("[data-ez-name]")

    // Add MutationObservers to all ad containers
    ads.forEach(function(ad){
        observer = new MutationObserver(mutationCallback);
        observer.ad = ad
        observer.observe(ad, {
            childList: true,
            subtree: true
        })
    })

    function mutationCallback(mutations, observer) {
        for(var mutation of mutations) {
            if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(function(addedNode) {
                    if (addedNode.nodeName.toLowerCase() == "iframe") {
                        addedNode.addEventListener('load', function(){
                            trackEzoicAdImpression(observer.ad)
                        })
                    }
                })
            }
        }
    }

    function trackEzoicAdImpression(elem) {
        var adFrame = elem.querySelector("iframe")

        window.dataLayer = window.dataLayer || []
        window.dataLayer.push({
            event: "ezoic.adimpression",
            ezoic: {
                adimpression: {
                    width: adFrame.scrollWidth,
                    height: adFrame.scrollHeight,
                    placement: elem.dataset.ezName
                }
            }
        })
    }
})()
</script>

How this works

  1. We find all of the afforementioned ad containers with the [data-ez-name] selector
  2. We attach MutationObserver instances to them
  3. The MutationObserver calls our mutationCallback function every time an element inside one of the ad container changes. If an iframe was added to the ad container, we attach a load event listener to it.
  4. This event listener will call the final trackEzoicAdImpression once the iframe (and our ad in it) has finished loading.
  5. trackEzoicAdImpression will then get the ad’s size and placement name and push an ezoic.adimpression event to dataLayer.

From there, you can then create a trigger in Google Tag Manager which reacts to this ezoic.adimpression and fires of a Google Analytics event. You can then use Data Layer Variables to access the dataLayer information (like ezoic.adimpression.placement) and include them in the Google Analytics event.

0 values in width and height attributes

If you spot 0 values in the width and height attributes of your dataLayer events, this could be because your ads are hidden. Check if your ads are loaded but not shown, e. g. because they’re in a sidebar which is hidden with CSS on smartphones due to the lack of space.
If you don’t want to track those impressions, you can check for those 0-values in Google Tag Manager and prevent them from triggering Google Analytics events. The more sustainable and performance-oriented solution though would be to not load the ads in the first place if they’re not going to be shown.