Skip to content

Instantly share code, notes, and snippets.

@bluesmoon
Last active September 10, 2019 16:27
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 bluesmoon/351ea5b2815606863a2de2c4889e8016 to your computer and use it in GitHub Desktop.
Save bluesmoon/351ea5b2815606863a2de2c4889e8016 to your computer and use it in GitHub Desktop.
This is a loader snippet for boomerang that doesn't use the iframe except for legacy browsers, and does not use document.write

Moved to https://developer.akamai.com/tools/boomerang#mPulseNon-BlockingLoaderSnippet

This is a loader snippet for boomerang (https://github.com/soasta/boomerang) that doesn't use the iframe except for legacy browsers, and does not use document.write

If an iframe is required, it is injected into the page immediately or soon after the script, so you may place the script wherever in the HTML you would like the iframe to show up.

For IE6 & 7, we will fallback to a same-window iframeless dynamic script node. This does mean that the script will be a Single Point of Failure for these two browsers, but given the low combined market share of these two browsers, the choice is between not getting any beacons for these browsers or potentially being a SPoF for users of these browsers.

You MUST include everything, including the <script> node with exactly the same id attribute. Replace "YOUR-API-KEY-GOES-HERE" with your actual API key (in quotes)

It is best to use boomerang version 1.571 or higher with this loader.

This loader and its CSP compliance is documented at https://calendar.perfplanet.com/2018/a-csp-compliant-non-blocking-script-loader/

// Code moved to https://developer.akamai.com/tools/boomerang#mPulseNon-BlockingLoaderSnippet
@steveworkman
Copy link

Thanks Philip.

I've turned this into an ES6 class for when we load this, and I've made some modifications to the element placement.

Basically, we're working on a theory that Google isn't parsing our canonical URLs correctly because there's an <iframe> element in the , which is semantically incorrect and those aren't allowed there. So, I've changed the where variable into a head variable instead for the preload link method, and if we fall back to the iframe it'll be appended to the end of the body.

Also, the doc variable in the iframe_loader method isn't used at all. Is that intentional?

class mPulse {
		constructor(apikey) {
			if (window.BOOMR && (window.BOOMR.version || window.BOOMR.snippetExecuted)) {
				return;
			}
			window.BOOMR = window.BOOMR || {};
			window.BOOMR.snippetExecuted = true;
			const BOOMRURL = `https://s.go-mpulse.net/boomerang/${apikey}`,
				LOADER_TIMEOUT = 3000;
			var promoted = false,
				head = document.head;
			function promote() {
				var s;
				s = document.createElement('script');
				s.id = 'boomr-scr-as';
				s.src = this.href;
				// not really needed since dynamic scripts are async by default and the script is already in cache at this point,
				// but some naïve parsers will see a missing async attribute and think we're not async
				s.async = true;
				head.appendChild(s);
				window.BOOMR_API_key = apikey;
				promoted = true;
			}

			function iframe_loader() {
				promoted = true;
				var dom,
					doc,
					iframe = document.createElement('iframe'),
					win = window;
				function boomerangSaveLoadTime(e) {
					win.BOOMR_onload = (e && e.timeStamp) || new Date().getTime();
				}
				if (win.addEventListener) {
					win.addEventListener('load', boomerangSaveLoadTime, false);
				} else if (win.attachEvent) {
					win.attachEvent('onload', boomerangSaveLoadTime);
				}
				iframe.src = 'javascript:void(0)';
				iframe.title = '';
				iframe.role = 'presentation';
				(iframe.frameElement || iframe).style.cssText = 'width:0;height:0;border:0;display:none;';
				win.document.body.appendChild(iframe);
				try {
					win = iframe.contentWindow;
				} catch (e) {
					dom = document.domain;
					iframe.src = "javascript:var d=document.open();d.domain='" + dom + "';void(0);";
					win = iframe.contentWindow;
				}
				win.document.open();
				win._boomrl = function() {
					var js = win.document.createElement('script');
					if (dom) {
						win.document.domain = dom;
					}
					js.id = 'boomr-if-as';
					js.src = BOOMRURL;
					BOOMR_lstart = new Date().getTime();
					win.document.body.appendChild(js);
				};
				if (win.addEventListener) {
					win.addEventListener('load', win._boomrl, false);
				} else if (win.attachEvent) {
					win.attachEvent('onload', win._boomrl);
				}
				win.document.close();
			}
			var l = document.createElement('link');
			if (l.relList && typeof l.relList.supports === 'function' && l.relList.supports('preload') && 'as' in l) {
				l.href = BOOMRURL;
				l.rel = 'preload';
				l.as = 'script';
				l.addEventListener('load', promote);
				l.addEventListener('error', iframe_loader);
				setTimeout(function() {
					if (!promoted) {
						iframe_loader();
					}
				}, LOADER_TIMEOUT);
				head.appendChild(l);
			} else {
				iframe_loader();
			}
			if (window.addEventListener) {
				window.addEventListener('message', function(e) {
					if (e && e.data && e.data.boomr_mq) {
						window.BOOMR_mq = window.BOOMR_mq || [];
						window.BOOMR_mq.push(e.data.boomr_mq);
					}
				});
			}
		}
	}

	return mPulse;

@bluesmoon
Copy link
Author

Hi Steve. Appending to the end of body for legacy browsers won't work because body may not exist when the loader runs. Since Google does not run as a legacy browser, it shouldn't matter where the iframe goes. Injecting it before the loader means that you can place the loader in the body if you want the iframe to go there.

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