Snapchat Ads and Preloading: How to Avoid Inaccurate Analytics

Learn how to capture true pageviews and sessions from people who visit your site through ads with preloading enabled

Snapchat isn’t just for selfies — it’s also a popular advertising platform. Snapchat ads function similarly to Instagram or Pinterest ads, where a person is shown a short image or video and can swipe to view the full website or product. For these ads, Snapchat recommends enabling a preload setting that loads the site experience in the background of the ad, before a user actually swipes to enter the site. Preloading reduces the user’s perceived site load time, allowing for a smoother transition from ad to site. While this approach can improve user experience, it causes incorrect analytics data without further adjustment.

When an ad preloads a site in the background, it triggers analytics to fire. Because most people who preload a website don’t actually visit the website, tools such as Google Analytics report inflated pageviews, sessions, and bounce rates. Because ads often get thousands of impressions per day, this issue can cause a large analytics disruption, making it difficult to evaluate the true performance of an ad campaign.

This article will show you how you can avoid these analytics pitfalls, using Google Tag Manager to capture only true pageviews and sessions from people who actually visited your website from your Snapchat ads.

The Solution

You can use the Page Visibility API to listen for true page views. In Google Tag Manager, add the following script as a Custom HTML tag:

<script>
   try {
      var vendorHidden;
      var visibilityChange;
      if (typeof document.hidden !== 'undefined') {
         // Opera 12.10 and Firefox 18 and later support
         vendorHidden = 'hidden';
         visibilityChange = 'visibilitychange';
      } else if (typeof document.mozHidden !== 'undefined') {
         vendorHidden = 'mozHidden';
         visibilityChange = 'mozvisibilitychange';
      } else if (typeof document.msHidden !== 'undefined') {
         vendorHidden = 'msHidden';
         visibilityChange = 'msvisibilitychange';
      } else if (typeof document.webkitHidden !== 'undefined') {
         vendorHidden = 'webkitHidden';
         visibilityChange = 'webkitvisibilitychange';
      } else if (typeof document.oHidden !== 'undefined') {
         vendorHidden = 'oHidden';
         visibilityChange = 'ovisibilitychange';
      }
      var date = new Date();
      var currentTime = date.getTime();
      var startTime = currentTime;
      var getChangeTime = function () {
         try {
            date = new Date();
            currentTime = date.getTime();
            var changeTime = date.getTime() - startTime;
            return Math.round(changeTime / 1000);
         } catch (e) {}
      };
      var handleVisibilityChange = function (customState) {
         try {
            if (customState !== true && customState !== false) {
               customState = document[vendorHidden] ? false : true;
            }
            dataLayer.push({
               'event': 'gtm.page.visibility.event',
               'page-visible': customState,
               'time-change': getChangeTime(),
            });
            startTime = currentTime;
         } catch (e) {}
      };
      if (
         typeof document.addEventListener === 'undefined' ||
         typeof document[vendorHidden] === 'undefined'
      ) {
         // Not Supported
      } else {
         // Handle page visibility change
         if (typeof window.addEventListener != 'undefined') {
            window.addEventListener(
               'beforeunload',
               function (event) {
                  handleVisibilityChange(false);
               },
               false
            );
         }
         // Send user's inital visibility state
         dataLayer.push({
            'event': 'gtm.page.visibility.initial',
            'page-visible': document.visibilityState === 'visible',
            'time-change': getChangeTime(),
         });
         // If user's visibility state changes, send new event
         document.addEventListener(
            visibilityChange,
            function (event) {
               handleVisibilityChange();
            },
            false
         );
      }
   } catch (e) {}
</script>

The script fires an event to the dataLayer any time the page visibility changes — such as when a user minimizes their window — as well as an initial visibility event for the first time the page comes into view on a user’s screen.

Then, you can use the initial visibility event, shown in the code above as “gtm.page.visibility.initial”, to create a trigger that listens for an initial, visible page view:

You can then use this trigger to fire any analytics tags that would otherwise fire on page load:

Firing your pageview tag on initial page visibility, rather than page load, will allow you to exclusively capture sessions from the point of a user’s first true page view. This solution does not impact traffic from other channels, and it effectively removes noise from Snapchat ads impressions when preloading is enabled.

Testing the Solution

To validate your solution, you can create test ads in Snapchat and enable preloading:

After creating an ad, you have the option to preview it by opening Snapchat on your mobile device and scanning a QR code:

The QR code launches an interactive preview of the ad within Snapchat with functionality to swipe to enter the site. To test the GTM solution, you can isolate and track your sessions using GA’s real time report, verifying that no sessions are tracked until you actually swipe up on your test ad — and that all interactions are tracked accurately once you have swiped to the site.

With this solution in place, we have the best of both worlds — an optimized user experience and accurate analytics tracking. You can use this code in any situation where preloading may disrupt analytics tracking, including Instagram and Pinterest ads.

Sign up for The Viget Newsletter

Nobody likes popups, so we waited until now to recommend our newsletter, a curated periodical featuring thoughts, opinions, and tools for building a better digital world. Read the current issue.