Dynamic image request based on url
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

Looking to get a quick demo of a script that will update a pixel request based on the url it is running on. Here is the scenario

We will have some embed code we will give our partner sites.

pixeldomain.com/partner.js

We want them to simply grab this js script code which will handle everything for them. The javascript will run on load and grab the url that is in the browser on the partner site

partnerdomain.com/somepage?=some-params

and will update the remote gif image that is called for the page. using the hypothetical url above it would be the image name like this (simple url encoding)

https://pixeldomain.com/partnerdomain.com%2Fsomepage%3F%3Dsome-params.gif

we arent looking to do cookies or any sort of user tracking, this is purely for page level tracking on the pages that the partner has embeded the js code on.

note:

-You can assume the remote js is the same domain as the gif pixel.

-Lets try to make the script work if on a SPA, so if it sees the url bar change urls even if the page is not fully refreshed then it will make another call to the updated gif
-Ideally code runs on all modern browsers including IE Edge.

ping pong
alv-c 2 months ago
Hey Qdev, have you had a chance to review solutions to this bounty?
bevan 1 month ago
2 months ago
Tags
javascript

Crowdsource coding tasks.

4 Solutions


partner.js

var __script = document.createElement("a");
__script.href = document.currentScript.src;
function updateGIF(gifID) {
    var link = window.location;
    var browserURL = link.host + link.pathname + link.search + link.hash;

    var scriptDomain = __script.protocol + "//" + __script.host;

    var gifURL = scriptDomain + "/" + encodeURIComponent(browserURL) + ".gif";
    document.getElementById("gif").src = gifURL;
}

window.onload = function() {
    updateGIF("gif");
}

window.onhashchange = function() {
    updateGIF("gif");
}

This assumes there's an <img id="gif"> in the document whose src needs to be updated.

For SPA's, onhashchange gets triggered when the part of the URL after # is updated.

Note: document.currentScript is supported by IE Edge, but not by IE 11 and lower.


;(function (window){
  function updateURL(){
    image.src = domain + encodeURIComponent(location.href.replace(location.protocol + '//', ''));
  }

  var domain = '//pixeldomain.com/',
      document = window.document,
      location = window.location,      
      current = document.currentScript || document.scripts[document.scripts.length-1],
      image = new Image();

  image.onload = function(){
    current.parentNode.insertBefore(image, current);
    image.onload = null;
  }

  window.addEventListener('popstate', updateURL, false);

  updateURL();
}(window));

I think this should work

!function(window, history, location) {
    const remote = 'https://pixeldomain.com/';

    const pushState = history.pushState;
    history.pushState = function(state) {
            if (typeof history.onpushstate == "function") {
                    history.onpushstate({state: state});
            }
            // ... whatever else you want to do
            // maybe call onhashchange e.handler
            return pushState.apply(history, arguments);
    };


    const log = () => {
        const current = encodeURIComponent(`${location.host}${location.pathname}${location.search}${location.hash}`);
        const url = `${remote}${current}.gif`;
        const gif = document.createElement('img');
        gif.src = url;
    }

    window.addEventListener('load', log);
    window.onhashchange = history.onpopstate = history.onpushstate = log;
}(window, window.history, window.location);

Here you have to modify the remote variable at the top of the code. This should work fine with regular apps
Angular, React, Vue apps as you can see it not only listens to hashchange but listens also to HTML5 history change event.

Also, the gif is not inserted into the page so it won't update the DOM and will be a little bit faster. The browser automatically fetches the image even if it's not inserted into the page.

Tell me if you need something else or doesn't work as expected. For example, if you want I could change the part where you have to manually put the remote url, and make it recognize itself based on the <script src=""> value.

Edit: Just to clarify, here, the history.pushState method is overwriten because if you use that method (and popular frameworks routing systems do), the popstate event won't be triggered. But it will be triggered now thanks to the rewrite


Explanation

Here is a solution that targets exactly your requirements without any overhead or unnecessary code. It supports SPAs and will generate the partner url without the protocol (http(s)) to unify the results in your tracking database.

How to use

Your partners will simple have to add the script tag before the closing </body> tag just like any other tracker (eg: Facebook Pixel or Google Analytics).

Code

;(function() {
    var pixelDomain = 'https://pixeldomain.com/';
    var pixel = document.createElement('img');

    updatePixelSource();
    document.body.appendChild(pixel);

    window.onpopstate = updatePixelSource.bind(this);
    window.onhashchange = updatePixelSource.bind(this);

    function updatePixelSource() {
        var partnerUrl = window.location.href.replace(window.location.protocol + '//', '');
        pixel.src = pixelDomain + encodeURIComponent(partnerUrl) + '.gif';
    }
})();

Code with documentation

// self executing code block with private scope to avoid conflicts
;(function() {
    // Domain containing the pixel gif
    var pixelDomain = 'https://pixeldomain.com/';

    // Html <img> tag generated by code
    var pixel = document.createElement('img');

    // Update the source of the img on load
    updatePixelSource();
    // Add the img to the page content to initialize the img load
    document.body.appendChild(pixel);

    // Add events to capture SPAs page change (old and new way of doing so)
    window.onpopstate = updatePixelSource.bind(this);
    window.onhashchange = updatePixelSource.bind(this);

    // Where the magic happens
    function updatePixelSource() {
        // Generate the partner url
        var partnerUrl = window.location.href.replace(window.location.protocol + '//', '');
        // Replace the <img> src with the encoded url and add .gif suffix
        pixel.src = pixelDomain + encodeURIComponent(partnerUrl) + '.gif';
    }

// end of self executing block and scope
})();
View Timeline