Skip to content

Instantly share code, notes, and snippets.

@nicjansma
Last active April 20, 2022 13:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicjansma/ddfd68286d99421ea66375ae2a854c5f to your computer and use it in GitHub Desktop.
Save nicjansma/ddfd68286d99421ea66375ae2a854c5f to your computer and use it in GitHub Desktop.
Boomerang plugin to repeat all beacons to a second URL.
/**
* Repeats all beacons to a second URL.
*
* To configure, update BEACON_URL.
*
* This code repeats some code from Boomerang. If you only need to send
* XHR beacons, or only image beacons, or not sendBeacon(), it could be trimmed down.
*
* @class BOOMR.plugins.BeaconRepeater
*/
(function() {
BOOMR = window.BOOMR || {};
BOOMR.plugins = BOOMR.plugins || {};
if (BOOMR.plugins.BeaconRepeater) {
return;
}
var BEACON_URL = "https://mybeaconurl.com/"
//
// Private implementation
//
var impl = {
initialized: false,
/**
* Gets a URI-encoded name/value pair.
*
* @param {string} name Name
* @param {string} value Value
*
* @returns {string} URI-encoded string
*
* @memberof BOOMR
*/
getUriEncodedVar: function(name, value) {
if (value === undefined || value === null) {
value = "";
}
if (typeof value === "object") {
value = BOOMR.utils.serializeForUrl(value);
}
var result = encodeURIComponent(name) +
"=" + encodeURIComponent(value);
return result;
},
/**
* Fired after the main Boomerang beacon is sent
*
* @param {object} data Beacon Data
*/
onBeacon: function(data) {
// send the beacon elsewhere after a short delay
setTimeout(function() {
var name, paramsJoined, url = [], useImg = false, w = BOOMR.window || window;
for (name in data) {
// if this var is set, add it to our URL array
if (data.hasOwnProperty(name)) {
url.push(impl.getUriEncodedVar(name, typeof data[name] === "undefined" ? "" : data[name]));
}
}
paramsJoined = url.join("&");
//
// Try the sendBeacon API first.
// But if beacon_type is set to "GET", dont attempt
// sendBeacon API call
//
if (w && w.navigator &&
typeof w.navigator.sendBeacon === "function" &&
BOOMR.utils.isNative(w.navigator.sendBeacon) &&
typeof w.Blob === "function") {
// note we're using sendBeacon with &sb=1
var blobData = new w.Blob([paramsJoined + "&sb=1"], {
type: "application/x-www-form-urlencoded"
});
if (w.navigator.sendBeacon(BEACON_URL, blobData)) {
return true;
}
// sendBeacon was not successful, try Image or XHR beacons
}
// If we don't have XHR available, force an image beacon and hope
// for the best
if (!BOOMR.orig_XMLHttpRequest && (!w || !w.XMLHttpRequest)) {
useImg = true;
}
if (useImg) {
//
// Image beacon
//
// just in case Image isn't a valid constructor
try {
img = new Image();
}
catch (e) {
BOOMR.debug("Image is not a constructor, not sending a beacon");
return false;
}
img.src = url;
}
else {
//
// XHR beacon
//
// Send a form-encoded XHR POST beacon
xhr = new (w.orig_XMLHttpRequest || BOOMR.orig_XMLHttpRequest || w.XMLHttpRequest)();
try {
impl.sendXhrPostBeacon(xhr, paramsJoined);
}
catch (e) {
// if we had an exception with the window XHR object, try our IFRAME XHR
xhr = new BOOMR.boomerang_frame.XMLHttpRequest();
impl.sendXhrPostBeacon(xhr, paramsJoined);
}
}
}, 0);
},
/**
* Sends XHR POST beacon data
*
* @param {object} data Beacon Data
*/
sendXhrPostBeacon: function(xhr, paramsJoined) {
xhr.open("POST", BEACON_URL);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(paramsJoined);
},
};
//
// Exports
//
BOOMR.plugins.BeaconRepeater = {
/**
* Initializes the plugin.
*
* This plugin does not have any configuration.
*
* @returns {@link BOOMR.plugins.BeaconRepeater} The BeaconRepeater plugin for chaining
* @memberof BOOMR.plugins.BeaconRepeater
*/
init: function() {
if (!impl.initialized) {
BOOMR.subscribe("beacon", impl.onBeacon, null, impl);
impl.initialized = true;
}
return this;
},
/**
* Whether or not this plugin is complete
*
* @returns {boolean} `true` if the plugin is complete
* @memberof BOOMR.plugins.BeaconRepeater
*/
is_complete: function() {
return true;
}
};
}());
@nicjansma
Copy link
Author

Minified (1,420 bytes):

!function(){if(BOOMR=window.BOOMR||{},BOOMR.plugins=BOOMR.plugins||{},!BOOMR.plugins.BeaconRepeater){var c="https://mybeaconurl.com/",s={initialized:!1,getUriEncodedVar:function(e,n){return null==n&&(n=""),"object"==typeof n&&(n=BOOMR.utils.serializeForUrl(n)),encodeURIComponent(e)+"="+encodeURIComponent(n)},onBeacon:function(a){setTimeout(function(){var e,n,t=[],o=!1,i=BOOMR.window||window;for(e in a)a.hasOwnProperty(e)&&t.push(s.getUriEncodedVar(e,void 0===a[e]?"":a[e]));if(n=t.join("&"),i&&i.navigator&&"function"==typeof i.navigator.sendBeacon&&BOOMR.utils.isNative(i.navigator.sendBeacon)&&"function"==typeof i.Blob){var r=new i.Blob([n+"&sb=1"],{type:"application/x-www-form-urlencoded"});if(i.navigator.sendBeacon(c,r))return!0}if(BOOMR.orig_XMLHttpRequest||i&&i.XMLHttpRequest||(o=!0),o){try{img=new Image}catch(e){return BOOMR.debug("Image is not a constructor, not sending a beacon"),!1}img.src=t}else{xhr=new(i.orig_XMLHttpRequest||BOOMR.orig_XMLHttpRequest||i.XMLHttpRequest);try{s.sendXhrPostBeacon(xhr,n)}catch(e){xhr=new BOOMR.boomerang_frame.XMLHttpRequest,s.sendXhrPostBeacon(xhr,n)}}},0)},sendXhrPostBeacon:function(e,n){e.open("POST",c),e.setRequestHeader("Content-type","application/x-www-form-urlencoded"),e.send(n)}};BOOMR.plugins.BeaconRepeater={init:function(){return s.initialized||(BOOMR.subscribe("beacon",s.onBeacon,null,s),s.initialized=!0),this},is_complete:function(){return!0}}}}();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment