最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to wait until tracking scripts have fired before redirecting the user? - Stack Overflow

programmeradmin3浏览0评论

I run a typical price comparison website, where the user browses products, then clicks on a link to go to the merchant's website.

Before being redirected to the merchant's website, the user is presented with a "we are redirecting you..." page.

This page is only there to allow tracking codes (Google Analytics, Adwords, Bing Ads...) to track the event.

I've placed the tracking codes right before the closing </body> tag, to avoid blocking the rendering of the page while the scripts are loaded.

I'm redirecting the user with a meta refresh tag:

<meta http-equiv="refresh" content="0; url=...">

It seems to work alright, but I'm worried that, depending on the browser / speed of the internet connection, the redirect can happen before the tracking scripts have fired.

I could just delay the redirect for a few seconds to be on the safe side, but I want to keep the experience smooth for the user.

I could also include the scripts in the <head>, but:

  • This would delay the display on the "redirecting..." page while the scripts are loaded
  • This would not guarantee that the tracking scripts have done their job before the user is redirected: the tracking script is first loaded, then triggers another action asynchronously to track the event.

How can I guarantee that the tracking scripts have done their jobs, while still redirecting the user ASAP?

Any feedback on a similar experience will be appreciated.

I run a typical price comparison website, where the user browses products, then clicks on a link to go to the merchant's website.

Before being redirected to the merchant's website, the user is presented with a "we are redirecting you..." page.

This page is only there to allow tracking codes (Google Analytics, Adwords, Bing Ads...) to track the event.

I've placed the tracking codes right before the closing </body> tag, to avoid blocking the rendering of the page while the scripts are loaded.

I'm redirecting the user with a meta refresh tag:

<meta http-equiv="refresh" content="0; url=...">

It seems to work alright, but I'm worried that, depending on the browser / speed of the internet connection, the redirect can happen before the tracking scripts have fired.

I could just delay the redirect for a few seconds to be on the safe side, but I want to keep the experience smooth for the user.

I could also include the scripts in the <head>, but:

  • This would delay the display on the "redirecting..." page while the scripts are loaded
  • This would not guarantee that the tracking scripts have done their job before the user is redirected: the tracking script is first loaded, then triggers another action asynchronously to track the event.

How can I guarantee that the tracking scripts have done their jobs, while still redirecting the user ASAP?

Any feedback on a similar experience will be appreciated.

Share Improve this question edited Sep 27, 2015 at 18:41 BenMorel asked Sep 21, 2015 at 9:39 BenMorelBenMorel 36.5k51 gold badges204 silver badges335 bronze badges 5
  • 4 Adobe Omniture simply forwards after 500ms - which seems a much more intelligent thing to do. A half second wait is bearable but if your scripts would load slowly, you require the users to wait for as long as your server might not respond quickly. So assume the scripts do their job in 500ms and otherwise you will lose some tracking. This is the best compromise between tracking a user and providing a good user experience. – somethinghere Commented Sep 21, 2015 at 9:41
  • Did you consider using Javascript Promises, particularily the Promise.all() method? – Supersharp Commented Sep 30, 2015 at 6:51
  • I don't know, is that implemented by these tracking scripts? – BenMorel Commented Sep 30, 2015 at 16:28
  • @Benjamin Could you show us the code of this redirect page? Because there are so many solutions for the problem you have, that I think it's better to see your exact situation to give you the best solution that fits to it. – Buzinas Commented Oct 2, 2015 at 15:44
  • @somethinghere Your comment is very true, I might just be over-thinking the thing. I'll probably just wait for half a second before redirecting, at least for now. My ideal solution would redirect as soon as tracking scripts have done their jobs (this might very well take less than 500ms), with a timeout of one second or so. This would just be perfect, but it might be quite complicated for such a small detail. – BenMorel Commented Oct 4, 2015 at 20:19
Add a comment  | 

6 Answers 6

Reset to default 5 +200

For Google analytics there is an official way to do this by tracking outbound links as 'events'. You need to set up an onclick function as below, and Google will call a callback when it has received the analytics message.

js

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-0000000-5', 'auto');
ga('send', 'pageview');

var trackOutboundLink = function(url) {
    ga('send', 'event', 'outbound_link', url,
        {
            'hitCallback': function () {
                document.location = url;
            }
        }
    );
};

html

<a href='<url>' onclick="trackOutboundLink('<url>'); return false;'>buy me now</a>"

return false prevents the link being followed as such, and leaves it to trackOutboundLinks to redirect to the new Url when called back by GA.

Let me know if you need more. For example I use more granularity in my event calls to distinguish between links to the websites of the product and websites where you can purchase.

TL;DR In short, every library has their own way of tracking users. You should handle every library differently and redirect when they all finished. Below, I've explained the different ways of tracking I could think of on the top of head. Especially, pay attention to the beacons part, I haven't seen it between the answers here, though it will be used more and more in the future I think.

This actually depends on the way other parties track the users. In general, I think there are three kind of ways to track a user. JavaScript, images and (maybe) iframes. Some methods allow you to check if the tracking is done. I'll try to explain the different methods. In short, per 3rd party you'll have to check if they finished tracking the user and redirect when all have finished (using window.location).

1. Javascript

In JavaScript, tracking can be implemented in different ways. I can think of 4 different methods on the top of my head. I'll try to explain how you can track if everything is loaded and processed correctly.

1.1. Beacons

Beacons are not very well known. It is a new technology, which allows the browser to send small packets of data to the server before the page unloads. Those are the easiest to handle. At the moment the page has unloaded (so after the redirect is initiated) they can still send their final data to the server. In short, don't worry to much about this way.

(But be aware, this is not yet supported in every browser. If you want to read more about it, please see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon . I'm not sure, but I thought Google Analytics was using this).

1.2. AJAX Requests

The AJAX requests are the most difficult. I see others have suggested $.ajaxComplete from the jQuery library. It's worth a try, but I'm not sure if you can catch AJAX calls which are made from scripts that are loaded from a different domain. From the same domains should work, I've used this myself to keep track of the AJAX calls on a page. You could test this however. Take two domains. On the first domain, use jQuery to catch the AJAX calls. On the second domain, host a file which makes an AJAX call (without using jQuery). This way, you should be able to find out if this works.

Otherwise, you should check if the libraries have a callback method for their tracking methods. Once this callback is called, you can assume the tracking part has finished.

1.3. Append image

With JavaScript, it is also possible to append an image tag to the HTML. In short, see the section below about tracking images. But, you will need to write some small piece of JavaScript to detect the tracking pixel which is appended. I think most libraries will add something to the image so you can identify them with JS.

1.4. Append iframe

Of course, appending an iframe is also an option. I don't think it will be used that often in combination with JavaScript, but the idea should be the same as with the tracking pixels.

2. Images

Images should not be that difficult. If you place the images in the body yourself, add a certain class or ID and use jQuery's load event. Again, I'm not sure this will always launch, but there are ways which can make you sure it does. For example, see this questions on SO: Check if an image is loaded (no errors) in JavaScript

For the tracking pixels append with JavaScript, if the always use a certain class, you write some JavaScript right after the <body> tag. For example:

<body>
<script type="text/javascript">
    $(document).on('load', '.trackingPixelClass', function () {
        // increase counter and check if every tracking work is done
    });
</script>

3. IFrames

IFrames should be the same as tracking if images are done. This should work, but I'm not a 100% certain what happens if the iframe loads content from another domain. Browsers might think this is a security risk.

There are a few solutions that come to my mind, I'll show you the one I think it fits best for your case.

Although, there is one single pre-requisite for this solution to work: you must take a look what their code does, so you can figure out what global object is created when the script is run. All those tracking codes generate global variables, so the code below should work as a piece of cake.

For example, the Google Analytics creates a ga object, and as soon as it's fully loaded, it creates an answer property with a value 42in this object, so, you could do:

document.addEventListener('DOMContentLoaded', function() {
  function check(arr, callback) {        
    if (arr.filter(function(item) {
      var final = window;
      
      item = item.split('.');
      
      for (var i = 0; i < item.length; i++)
        final = final[item[i]];      
      
      return typeof final !== 'undefined' ? true : false;    
    }).length < arr.length) {
      setTimeout(function() { check(arr, callback) }, 0);
      return;
    }
    callback();
  }

  check(['ga.answer'], function() {
    location.replace('http://www.pudim.com.br/'); // change it to the merchant's website
  });
});

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-0000000-5', 'auto');
ga('send', 'pageview');
Redirecting...

The code above keeps calling a check function until all the elements are already loaded, and then, as soon as they are all available, it immediately redirects the user to the page you want.

Note: You can pute the code above anywhere in your page (better to put it inline than in a separate file).

The answer really depends on what "trackers" you use. Some of them use asynchronous calls which are hard to track.

Your best bet is to check if all of them provide callbacks and hen count them, and if they all fire use javascript window.location to redirect user instead of meta-refresh.

Another option would be to check which elements appear when those scripts finish loading, then wait either till they all appear or preset max number of seconds and redirect the user.

When you have a Javascript element, the page loading is halted. the script loads and run, then your page continues, unless you mark it async, that makes the script loading asynchronous.

This example loads google webpage but only after the script is executed, note that the second script is not on the main HTML. Create these three files on a folder:

file test.htm

<html>
<head>
<script src="test.js"></script>
<meta http-equiv="refresh" content="0; url=http://www.google.com/">
</head>
<body>Text
</body>
</html>

file test.js

document.write('<script src="test2.js"></script>');

file test2.js

alert('Hello');
img = new Image();
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Googlelogo.png/800px Googlelogo.png';
alert('Loaded image ' + img.outerHTML); // Note sure about this
alert('Will redirect now.');

The alerts are at the second script file, and they run before the redirect. You will see the text "Text" only after the alerts, and the browser will load the next page.

Of course this depends on how the script works. If it puts an onload event and write some img element on the body, it may not work, or work sometimes (that is the worst case because you may think it is ok).

I am not really sure about the new Image, but I think it works.

If the tracking codes depends on document loading, you may try to use the document.onload or a specific function from the tracking mechanism API.

You will have to test your specific case.

The image element constructor: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image

There is information about javascript synchronicity here, on the answers and their links: When is JavaScript synchronous?

Another idea would be to use $.ajaxComplete to capture the ajax responses (made by tracking providers), and then redirect the user to the specified page.

But I don't know if $.ajaxComplete() also captures non-jquery ajax requests.

发布评论

评论列表(0)

  1. 暂无评论