Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send information about clicked link to the server before redirect

We're creating a click tracking app, that builds heatmaps. I'm writing a script which users are suppose to insert into their pages for tracking to work.

It works fine on elements, which doesn't require a redirect or form submit. For example, if I click on h1 or p or whatever, it works perfectly correct. But, if I click on a a, request to our server never happens before the normal redirect.

In the last couple of days I tried a lot of ways to do that. First of, I tried a normal AJAX call, since it was a cross-domain request I had to use JSONP, but again, that AJAX call did not have time to execute before the redirect. Adding async: false would have solved the problem, but it doesn't work with JSONP requests. So I decided to add a flag variable which indicates that it is safe to move on with redirect and used an empty while loop to wait until it becomes try in the ajax callback. But the while loop was blocking the execution flow, so callback never got a chance to set that variable to true. Here is some simplified code:

$(document).on('click', function (e) {
    //part of the code is omitted 
    $.ajax({
        url: baseUrl,
        data: data,
        type: "get",
        dataType: "jsonp",
        crossDomain: true,
        complete: function (xhr, status,) {
            itsSafeToMoveOn = true;
        }
    });

    while(!itsSafeToMoveOn){}

    return true;
});

The next thing I tried is to use unload page event to wait until total ajax calls in progress would become zero (I had a counter implemented) and then to move on with redirect. It worked in Firefox and IE, but in WebKit there was this error:

Error: Too much time spent in unload handler

After that I realized that I don't care about the server response and using img.src for the request would be an ideal fit for this case. So at this point code looks like this:

$(document).click(function (e) {
    //part of the code is ommited
    (new Image).src = baseUrl + '?' + data;

    if (tag === "a" || clickedElement.parents().has("a")) {
        sleep(100); 
    }

    return true;
});

That way I increased the overall script performance slightly, but problem with links remains unchanged. The sleep function appears to be also blocking the execution flow and request never happens.

The only idea left is to return false from the event handler and than redirect manually to the clicked element's href or to call submit() on the form, but it will complicate things to much and believe me it's already a huge pain in the ass to debug this script in different browsers.

Does anyone have any other ideas?

like image 993
Max Al Farakh Avatar asked Apr 24 '12 09:04

Max Al Farakh


2 Answers

var globalStopper = true;

$(document).on('click', function (e) {
    if (globalStopper === false)
        return true; //proceed with click if stopper is NOT set
    else {
        globalStopper = false; //release the breaks

        $.ajax({
            //blahblah
            complete: function (xhr, status,) {
                $(elem).click(); //when ajax request done - "rerun" the click
            }
        });
        return false; //DO NOT let browser process the click
    }
});

Also, instead of adding image, try adding script. And then add the script to the HEAD section. This way the browser will "wait" until it's loaded.

 $(document).on('click', function (e) {
     var scriptTag = document.createElement("script");
     scriptTag.setAttribute("type", "text/javascript");
     scriptTag.setAttribute("src", url);
     document.getElementsByTagName("head")[0].appendChild(scriptTag);
     return true;
 }
like image 171
Alex from Jitbit Avatar answered Oct 28 '22 13:10

Alex from Jitbit


I would take a look at the navigator sendBeacon API mentioned in this stack overflow answer or directly linked to here.

From the description on the site

navigator.sendBeacon(url, data) - This method addresses the needs of analytics and diagnostics code that typically attempts to send data to a web server prior to the unloading of the document.

like image 27
origamifreak2 Avatar answered Oct 28 '22 15:10

origamifreak2