A Better Javascript For Google Consumer Surveys - ΩJr. Software Articles and Products

This information lives on a web page hosted at the following web address: 'https://omegajunior.globat.com/code/'.

The script Google provides is slow, dangerous, and time-consuming, drawbacks that this better one overcomes.

Google allows webmasters to monetize their websites by hosting surveys for other companies on their own websites. After signing up (an AdSense Account is needed), Google lets us copy and paste some coding into our web pages.

The New and Improved Google Consumer Surveys Script

<script async="async" id="GCS402Script"></script>
<script id="GCSPromptEmbedStaticScript"></script>
<script id="GCSPromptSurveyScript"></script>
<script>/* <!CDATA[ */
var my = my || ({});
my.ranShowGCS = false;
my.gcsid = "_Your-GSC-Account-ID";

(function(url, random) {
"use strict";
var d, s, id = "GCS402Script";
try {
if (d = window.document) {
if (s = d.getElementById(id)) {
s.src = [ "//survey.g.doubleclick.net/survey?site=", my.gcsid, "&url=", encodeURIComponent( url ), "&cid=everything&random=", random ].join('');
}
}
} catch ( err ) {
console.log( err.toString() );
}
})( window.location.href, (new Date).getTime() );

my.stopPollingFor402 = function () {
"use strict";
window.clearInterval( my.handle402Poll );
my.handle402Poll = null;
};

my.loadPrompterStaticScript = function () {
"use strict";
var d, s, id = "GCSPromptEmbedStaticScript", noErrors = true;
try {
if (d = window.document) {
if (s = d.getElementById(id)) {
s.src = "//survey.g.doubleclick.net/insights/consumersurveys/static/383255019405518060/prompt_embed_static.js";
}
}
} catch ( err ) {
console.log( err.toString() );
noErrors = false;
}
return noErrors;
};

my.applyPremiumContentClass = function () {
"use strict";
var b = false, d, e, i = 0, n;
try {
if (d = window.document) {
if (n = d.body.getElementsByTagName( "div" )) {
i = n.length;
while ( i ) {
i -= 1;
e = n[ i ];
if (!!e) {
if (e.className) {
if ( e.className == "body" ) {
e.className += " p402_premium";
b = true;
i = 0;
}
}
}
}
}
}
} catch ( err ) {
console.log( err.toString() );
}
return (b ? e : null);
};

my.addSurveyPlaceHolder = function ( divPremiumContent ) {
"use strict";
var d, m, noErrors = true;
try {
if (divPremiumContent) {
if (d = window.document) {
if (m = d.createElement( "div" )) {
m.id = "contain-402";
m.style.cssText = "display:none";
divPremiumContent.parentNode.insertBefore(m, divPremiumContent);
m = null;
}
}
}
} catch ( err ) {
console.log( err.toString() );
noErrors = false;
}
return noErrors;
};

my.loadPromptingScript = function () {
"use strict";
var d, id = "GCSPromptSurveyScript", noErrors = true, s;
try {
if ( my.ranShowGCS ) {
return false;
}
my.ranShowGCS = true;
if (d = window.document) {
if (s = d.getElementById(id)) {
s.src = [ "//survey.g.doubleclick.net/prompt?site=", my.gcsid, "&t=1", "&url=", encodeURIComponent( window.location.href ), "&cid=everything&random=", _402.timingTrStart, "ref=", encodeURIComponent(document.referrer.substr(0, 500)) ].join('');
}
}
} catch ( err ) {
console.log( err.toString() );
noErrors = false;
}
return noErrors;
}

my.pollFor402Object = function () {
"use strict";
if (typeof _402 !== "undefined") {
my.stopPollingFor402();
if ( my.loadPrompterStaticScript() ) {
if ( my.addSurveyPlaceHolder(my.applyPremiumContentClass()) ) {
return my.loadPromptingScript();
}
}
}
return false;
};

my.handle402Poll = window.setInterval(my.pollFor402Object, 1000);
/* ]]> */</script>

Copy this and paste it into your web page template, right before the HTMLBodyElement closes (</body>).

Look for the text “_Your-GSC-Account-ID” on line 7 and change it into your own Google Consumer Surveys account ID.

You need to make another change, but therefore you must understand what the script does. So let’s look at the:


Breakdown of the Javascript Coding

We start out by adding 3 HTMLScriptElements that have no “src” attribute. We will be assigning values to their “src” attribute later on. This is necessary because they require the existence of memory variables that get created by the javascript resources we will be loading in the correct order. For the same reason only 1 script element has set the “async” attribute.

On line 5 we declare and instantiate “my”, our “namespace” for our functions and variables, thereby making it unlikely that other javascript sources overrule the functions and variables we declared. Technically it is a Javascript object variable, which serves the namespace purpose.

An anonymous function is declared on line 9. This function gets executed instantly upon the browser's parsing. It loads into the browser's memory the first required external javascript resource, which contains the “_402” Google Consumer Survey Object. It is specific to the web page and your GCS account ID, it declares and instantiates the “_402.timingTrStart” variable, as well as the methods “_402.show()” and “_402_Show()”, which will be used later on.

On line 23 we declare the function “stopPollingFor402()” and add it to “my” namespace. This function does what its name says: it stops the browser from polling for the “_402” Google Consumer Survey Object.

The function “loadPrompterStaticScript()” is declared and added to “my” namespace on line 29. This method loads the 2nd required javascript resource into the browser's memory. We need this function because Google's own method uses “document.write()”, which in 2007 we have proven to behave inconsistently, and which fails in strict-security browsers, causing no surveys to be shown.

Then, on line 45, we declare the function “applyPremiumContentClass()” and add it to “my” namespace. This function is one you need to change. We'll discuss how, further down.

The documentation about Google Consumer Surveys tells us to mark our premium content elements with the CSS class “p402_premium”. Since we refuse to change all of our templates, we chose to write this javascript function, which looks for the first HTMLDivElement with CSS class “body”, adds “p402_premium” to its “className” attribute, and then returns it for processing by the next function.

On line 72 we declare the function “addSurveyPlaceHolder()” and add it to “my” namespace. This method also does what its title says: it adds an HTMLDivElement with “id” “contain-402” immediately above the HTMLDivElement returned by the function “applyPremiumContentClass()”.

Google Consumer Surveys needs this div. It is created by the static prompt script, but, yet again, Google used the dangerous “document.write()” method which fails in safer web browsers, and therefore has to be replaced with the more acceptable DOM 2 manipulation “document.insertBefore()”, which has been a recommendation since the year 2000, and is used in other, better-behaving javascripts (by Google, too).

The function “loadPromptingScript()” is declared on line 93 and added to “my” namespace. This method loads the last required javascript resource, which is dynamic rather than the static one we loaded earlier. It is used to ask the web page visitor whether or not they wish to participate in a Google Consumer Survey. It requires the value of the “_402.timingTrStart” javascript property declared and instantiated by the “_402” Google Consumer Survey Object which we loaded in the anonymous function on line 9.

On line 113 we declare the function “pollFor402Object()” and add it to “my” namespace. This method checks for the existence of the “_402” object in the web browser's memory. If that object exists, the method stops the polling interval, and goes on to load the required resources using the functions described above.

And finally, on line 126 we tell the web browser to poll for the existence of the “_402” object at an interval rate of 1 second. We need to poll for the object because it gets created by the script that we are loading asynchronously using the anonymous function on line 9, causing us to be clueless about when we can start using the “_402” object.

In the original javascript coding, Google again employs “document.write()” to load that script. We already proved that was unreliable; it also (because of the advised placement immediately after opening the HTMLBodyElement) causes the web browser to both wait for the resource and rerender the webpage, slowing it down in the best of conditions, and wiping it out entirely to substitute it with the raw javascript, in the worst of conditions. This causes a bad user experience.


The Change Required to Function “applyPremiumContentClass()”

In the web pages generated by our Publizjr Page Publication System, the main article text lives in an HTMLDivElement with a CSS class “body”. Therefore, function “applyPremiumContentClass()” runs through all divs, looks for ones that have “body” as their className, and tacks on another name: “p402_premium”.

This new class name is what Google Consumer Surveys looks for, and thinks of the contents of elements bearing this name as “premium content”. Now, the documentation about Google Consumer Surveys has not, as far as we have seen, specified what it considers premium content. Therefore marking the main article content as such is based on an assumption that we are testing as we are writing this article.

In case our assumption proves wrong, we will be adjusting our script. But even in case it is correct, you probably still want to adjust function “applyPremiumContentClass()”, just because your particular web page generator template (you are using one, aren’t you?) might not place the main article content in a div with class name “body”.

For instance, if your generator template uses an HTMLArticleElement with class name “main”, your variation on this method could look like this:
my.applyPremiumContentClass = function () {
"use strict";
var b = false, d, e, i = 0, n;
try {
if (d = window.document) {
if (n = d.body.getElementsByTagName( "article" )) {
i = n.length;
while ( i ) {
i -= 1;
e = n[ i ];
if (!!e) {
if (e.className) {
if ( e.className == "main" ) {
e.className += " p402_premium";
b = true;
i = 0;
}
}
}
}
}
}
} catch ( err ) {
console.log( err.toString() );
}
return (b ? e : null);
};

Notice how we did not use element.classList.add()and document.querySelector() or document.querySelectorAll()? That’s because we actually have a small set of mobile devices on which we test out our software products, and one of those is an Apple iPad 1 with Mobile Safari 5.1. That is the latest version of Safari for that iPad: there is no updating. And unfortunately, it is not aware of these functions.

Now we could have said: well, just use a polyfill. We chose not to do that and set up a dedicated function, instead.

With element.classList.add() and document.querySelector() (if you don’t care about people stuck with older mobile devices), the coding for this function could look like this:
my.applyPremiumContentClass = function () {
"use strict";
var b = false, d, e;
try {
if (d = window.document) {
e = d.querySelector( "div.body" );
if (!!e) {
e.classList.add( "p402_premium" );
b = true;
}
}
} catch ( err ) {
console.log( err.toString() );
}
return (b ? e : null);
};

If you need help figuring this part out, please drop us a note? And if you value our help, please hit that “donate” button at the bottom of every page?


Dissecting the Original Script

We made some bold statements about the script provided by Google Consumer Surveys: it is slow, dangerous, and time-consuming. Well, let’s look at it and discuss our argumentation.

Part #1

Loads the survey programming. To be placed right after opening the HTMLBodyElement (<body>) of your web pages:

<script type="text/javascript">
(function() {
  var ARTICLE_URL = window.location.href;
  var CONTENT_ID = 'everything';
  document.write(
    '<scr'+'ipt '+
    'src="//survey.g.doubleclick.net/survey?site=_GCS-ACCOUNT-ID'+
    '&amp;url='+encodeURIComponent(ARTICLE_URL)+
    (CONTENT_ID ? '&amp;cid='+encodeURIComponent(CONTENT_ID) : '')+
    '&amp;random='+(new Date).getTime()+
    '" type="text/javascript">'+'\x3C/scr'+'ipt>');
})();
</script>


Part #2

Identify the web page’s premium content by wrapping it in a div with class name “p402_premium”, and then execute the function _402_Show();:

<div class="p402_premium">
  <!-- YOUR PREMIUM CONTENT HERE -->
</div>
<script type="text/javascript">
  try { _402_Show(); } catch(e) {}
</script>


Dangerous
Wait, what? It’s the year 2015, and Google is still forcing document.write() on us? Did we not already prove in 2007, that javascript injection is dangerous and unreliable, and should be replaced, using document.createElement() instead? In 2007! What has Google been doing?


Slow
Seriously, Google, doesn’t your own Mobile Page Speed checker complain all the time about how slow it makes web pages to include render-blocking blocking javascripts and css files? Yes, it does, doesn’t it? Then why does your own script for Consumer Surveys make us do just that?

Adding an HTMLScriptElement to the document tree in the way requested by script part #1 causes the web browser (in the best outcome of the possible rendering variations) to halt rendering, look up the requested javascript source, load it into browser memory, and continue rendering. In the mean time, the page visitor is looking at a blank screen.

And that is in the best-case scenario. In the worst case, the loaded javascript will be displayed instead of the requested web page. Nice user experience, Google! Not.

(We do understand why Google has us halt rendering before continuing: that is to make sure the “_402” object is loaded into memory before we invoke its “show()” method. We fixed that using our object polling interval, above.)


Time-Consuming
And finally, part #2 has us change every web page generating template (or worse, every web page) to wrap up our “premium content” in yet another bloody HTMLDivElement (<div>). For small websites that sport a handful of webpages, this might be doable.

For the ΩJr.Net, which has a little over 700 pages, it takes too long, even though we are using only about 10 different templates.

Imagine having to add this div to every web page by hand, using a tool like DreamWeaver… (shudders).

Luckily for us, we recently did redo all of our web page generation templates due to the upgrade to Publizjr 2, and the inclusion of Google Adsense. Since Consumer Surveys requires an AdSense account, we thought it appropriate to add the Consumer Surveys script to the AdSense script, and have it available to most of our web pages instantly.


Afterthoughts

The new and improved javascript coding shown at the top of this article can be made a little shorter by using a cross-browser javascript library that offers all kinds of shortcuts.

For instance, if you were using zjrJS, our free and open-source cross-browser javascript library, the coding could be made a bit smaller, but not by much (mostly due to our defensive programming).

However, if we would be able to use the javascript promises functionality promised in ES6 (see what we did there?), we could omit the entire polling for object “_402” functionality in favour of a fulfilled promise.

For now, we can make the script smaller by running it through Google Closure Compiler:

<script async="async" id="GCS402Script"></script>
<script id="GCSPromptEmbedStaticScript"></script>
<script id="GCSPromptSurveyScript"></script>
<script>/* <!CDATA[ */
var my=my||{};my.ranShowGCS=!1;my.gcsid="_Your-GSC-Account-ID";(function(c,b){var a,d;try{if(a=window.document)if(d=a.getElementById("GCS402Script"))d.src=["//survey.g.doubleclick.net/survey?site=",my.gcsid,"&url=",encodeURIComponent(c),"&cid=everything&random=",b].join("")}catch(e){console.log(e.toString())}})(window.location.href,(new Date).getTime());my.stopPollingFor402=function(){window.clearInterval(my.handle402Poll);my.handle402Poll=null};
my.loadPrompterStaticScript=function(){var c,b,a=!0;try{if(c=window.document)if(b=c.getElementById("GCSPromptEmbedStaticScript"))b.src="//survey.g.doubleclick.net/insights/consumersurveys/static/383255019405518060/prompt_embed_static.js"}catch(d){console.log(d.toString()),a=!1}return a};
my.applyPremiumContentClass=function(){var c,b,a=0,d,f=0;try{if(c=window.document)if(d=c.body.getElementsByTagName("div"))for(a=d.length;a;)--a,(b=d[a])&&b.className&&"body"==b.className&&(b.className+=" p402_premium",a=0,f=1)}catch(e){console.log(e.toString())}return f?b:null};my.addSurveyPlaceHolder=function(c){var b,a,d=!0;try{c&&(b=window.document)&&(a=b.createElement("div"))&&(a.id="contain-402",a.style.cssText="display:none",c.parentNode.insertBefore(a,c))}catch(e){console.log(e.toString()),d=!1}return d};
my.loadPromptingScript=function(){var c,b=!0,a;try{if(my.ranShowGCS)return!1;my.ranShowGCS=!0;if(c=window.document)if(a=c.getElementById("GCSPromptSurveyScript"))a.src=["//survey.g.doubleclick.net/prompt?site=",my.gcsid,"&t=1&url=",encodeURIComponent(window.location.href),"&cid=everything&random=",_402.timingTrStart,"ref=",encodeURIComponent(document.referrer.substr(0,500))].join("")}catch(d){console.log(d.toString()),b=!1}return b};
my.pollFor402Object=function(){return"undefined"!==typeof _402&&(my.stopPollingFor402(),my.loadPrompterStaticScript()&&my.addSurveyPlaceHolder(my.applyPremiumContentClass()))?my.loadPromptingScript():!1};my.handle402Poll=window.setInterval(my.pollFor402Object,1E3);
/* ]]> */</script>

which does work, but is a little hard to read and maintain.


What improvements would you make?

If you spot a mistake in our coding, or can offer other suggestions that can improve it, please let us know using the comments below? Thanks!

Need problem solving?

Talk to me. Let's meet for coffee or over lunch. Mail me at “omegajunior at protonmail dot com”.