Redirect document.write from javascript script - javascript

We want to serve ads on our site but the adserver we are in talks with has issues with delivering their advertising fast enough for us.
The issue as I see it is that we are supposed to include a <script src="http://advertiserurl/myadvertkey"></script> where we want to display the ad and it will then download a script and use document.write to insert some html.
Problem is that the call to the advertiser website is slowish and the code returned then downloads another file (the ad) which means the speed of rendering our pages slows while we wait for the request to be filled.
Is there a way to take the output from the document.write call and write this in after the page has loaded?
Basically I want to do this:
<html>
<body>
<script>
function onLoad() {
var urlToGetContentFrom = 'http://advertiserurl/myadvertkey';
// download js from above url somehow
var advertHtml = // do something awesome to interprete document.write output
$('someElement').innerHTML = advertHtml;
}
</script>
</body>
</html>
Or anything similar that will let me get the output of that file and display it.

If I understand correctly, you want to capture document.write to a variable instead of writing it to the document. You can actually do this:
var advertHtml = '';
var oldWrite = document.write;
document.write = function(str)
{
advertHtml += str;
}
// Ad code here
// Put back the old function
document.write = oldWrite;
// Later...
...innerHTML = advertHtml;
You still have the hit of loading the script file though.

To decouple the main page loading from the ad loading, you can put the ad in its own page in an iframe or, similarly, download the script file with AJAX and execute it whenever it comes down. If the former is not adequate, because of referring URI or whatever, the latter gives you some flexibility: you could use string replacement to rewrite "document.write" to something else, or perhaps temporarily replace it like "document.write = custom_function;".

You may be interesed in the Javascript library I developed which allows to load 3rd party scripts using document.write after window.onload. Internally, the library overrides document.write, appending DOM elements dynamically, running any included scripts which may use document.write as well.
I have set up a demo, in which I load 3 Google Ads, an Amazon widget as well as Google Analytics dynamically.

You'd run into some security issues going cross domain due to the Same Origin Policy. I would look into JSONP if you have access to change the advertising content/service
http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback

Related

phantomJS includeJs method always fails to load script via Operation Cancelled

I'm trying to load some scripts into my pages being visited by phantomjs. I'm using 2.1.1 btw.
I'm kind of banging my head here because I've tried a variety of things and they all seem to fail in the same way which kind of makes me think maybe I'm missing a configuration setting or something.
Any who what I'm trying :
//I dont actually care about using jquery, just trying loading from different servers
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js');
and
page.includeJs('https://aSiteIControl.com/jquery.min.js');
and then I have a onResourceError handler like this:
page.onResourceError = function(resourceError) {
console.error(resourceError.url + ': ' + resourceError.errorString);
console.error(JSON.stringify(resourceError))
};
that outputs this no matter what I've tried:
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js: Operation canceled
{"errorCode":5,"errorString":"Operation canceled","id":1,"status":null,"statusText":null,"url":"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"}
This seems to happen no matter what protocol I use or what server the script lives on. Also, both of those examples are visitable in a browser. Any body have any idea what I might be doing wrong?
TO BE CLEAR on the accepted answer since there is no code:
just go look at this question :
PhantomJS: injecting a script before any other scripts run
I bet you can include directly only local scripts. Please try:
(page.evaluate(function() {
var script = document.createElement('script');
script.src = 'http://urlToScript.com';
}))
This can be caused by a timeout or the call to the exit() function of the phantom object while the js is being loaded, or if you try to open another page. Can you add all your code?
Based on the documentation you can include external JS:
Includes external script from the specified url (usually a remote location)

How to Get Access to Page's Script Context

My addon uses a content script to interact with the page. But it also needs access to the page's javascript so it can run one of the page's routines. So my content script needs access to the page's script context.
Here's what I mean.
Addon uses main.js which access content.js and uses messaging to communicate.
But the web-page (into which content.js is being injected) has it's own javascript. My content.js needs access to that context so it can fetch the values from variables there.
How can one get that?
I have been reading these mdn docs, but it seems like they are talking about an html page that you code yourself, like you would for a preferences page. But in my case I am working with an external website, not something coded just for the addon.
The approach listed on the MDN page also works for external pages, not just your own.
I.e. unsafeWindow.myPageVar will work.
This works:
var script = document.createElement("script");
script.innerHTML = "alert( myPageVar );";
document.body.appendChild( script );
Credit goes to this fellow.
I don't know whether this is the best way to do this, however. I hope that someone else more knowledgeable than me will answer.
Here's how to return a value:
var retval = unsafeWindow.SomePageFunction();
alert(retval);
It's called "unsafe" because you never know what about the page might be changed or might change. That's how it when the addon interacts with page scripts.

Can I inject text links within the body of a web-page

I am coding a proof of concept for my boss, I am a backend developer and haven't done javascript in years so I don't know much about same origin policy and other obstacles.
He basically has a chrome plugin and wants to replace matching keywords with links to his service, this will happen in any domain the user visits and not just one, similar to in-text advertising.
I was also wondering if it's possible to do this with an iframe, without the need of a chrome extension.
You will need a Chrome extention for that and permisions for content scripts.
It takes a lot of improvement but basically what you want to do is this:
document.onload = function(){
var textToParse = document.body.innerHTML,
linkHTML = 'Your Boss\'s Service Reference',
newText = '';
textToParse.split('Your Boss\'s Service Reference').join(linkHTML);
document.body.innerHTML = newText;
}
WARNING: The above code is a basic example of how to do it but might cause problems if the search in textToParse matches something that is HTML code. You should use jQuery and other tools for an easier/more secure way to edit text within HTML elements.

how should my site handle ocassionally missing javascript files gracefully?

Say I've got this script tag on my site (borrowed from SO).
<script type="text/javascript" async=""
src="http://edge.quantserve.com/quant.js"></script>
If edge.quantserve.com goes down or stops responding without returning a 404, won't SO have to wait for the timeout before the rest of the page loads? I'm thinking Chaos Monkey shows up and blasts a server that my site is depending on, a server that isn't part of a CDN and has a poor failover.
What's the industry standard way to handle this issue? I couldn't find a dupe on SO, maybe I'm searching for the wrong terms.
Update: I should have looked a bit more closely at the SO code, there's this at the bottom:
<script type="text/javascript">var _gaq=_gaq||[];_gaq.push(['_setAccount','UA-5620270-1']);
_gaq.push(['_setCustomVar', 2, 'accountid', '14882',2]);
_gaq.push(['_trackPageview']);
var _qevents = _qevents || [];
(function(){
var s=document.getElementsByTagName('script')[0];
var ga=document.createElement('script');
ga.type='text/javascript';
ga.async=true;
ga.src='http://www.google-analytics.com/ga.js';
s.parentNode.insertBefore(ga,s);
var sc=document.createElement('script');
sc.type='text/javascript';
sc.async=true;
sc.src='http://edge.quantserve.com/quant.js';
s.parentNode.insertBefore(sc,s);
})();
</script>
OK, so if the quant.js file fails to load, it's creating a script tag with ga.async=true;. Maybe that's the trick.
Possible answer: https://stackoverflow.com/a/1834129/30946
Generally, it's tricky to do it well and cross-browser.
Some proposals:
Move the script to the very bottom of the HTML page (so that almost everything is displayed before you request that script)
Move it to the bottom and wrap it in <script>document.write("<scr"+"ipt src='http://example.org/script.js'></scr"+"ipt>")</script> or the way you added after update (document.createElement('script'))
A last option is to load it via XHR (but this works only for same-domain, or cross-domain only if the CORS is enabled on a third-party server); you can then use timeout property of the XHR (for IE and Fx12+), and in the other browsers, use setTimeout and check the XHR's readyState. It's kind of convoluted and very non-cross-browser for now, so the option 2 looks the best.
Make a copy of the file on your server and use this. it will load your copy only if the one from the server has failed to load
<script src="http://edge.quantserve.com/quant.js"></script>
<script>window.quant || document.write('<script src="js/quant.js"><\/script>')</script>
To answer your question about the browser having to wait for the script to load before the rest of the page loads, the answer to that would typically be no. Typical browsers will have multiple threads processing the download of the page and linked content (CSS, images, js). So the rest of the page should be loaded, though the user's browser indicator will still show the page trying to load until the final request is fulfilled or timed out.
Depending on the nature of the resource you are trying to load, this will obviously effect your page differently. Typically, if you are worried about this, you can host all your files on a common CDN (or your website if it is not that highly trafficked), that way at least if one thing fails, chances are everything is failing and you have a bigger issue to contend with :)

Detect and log when external JavaScript or CSS resources fail to load

I have multiple <head> references to external js and css resources. Mostly, these are for things like third party analytics, etc. From time to time (anecdotally), these resources fail to load, often resulting in browser timeouts. Is it possible to detect and log on the server when external JavaScript or CSS resources fail to load?
I was considering some type of lazy loading mechanism that when, upon failure, a special URL would be called to log this failure. Any suggestions out there?
What I think happens:
The user hits our page and the server side processes successfully and serves the page
On the client side, the HTML header tries to connect to our 3rd party integration partners, usually by a javascript include that starts with "http://www.someothercompany.com...".
The other company cannot handle our load or has shitty up-time, and so the connection fails.
The user sees a generic IE Page Not Found, not one from our server.
So even though my site was up and everything else is running fine, just because this one call out to the third party servers failed, one in the HTML page header, we get a whole failure to launch.
If your app/page is dependent on JS, you can load the content with JS, I know it's confusing. When loading these with JS, you can have callbacks that allow you to only have the functionality of the loaded content and not have to worry about what you didn't load.
var script = document.createElement("script");
script.type = "text/javascript";
script.src = 'http://domain.com/somefile.js';
script.onload = CallBackForAfterFileLoaded;
document.body.appendChild(script);
function CallBackForAfterFileLoaded (e) {
//Do your magic here...
}
I usually have this be a bit more complex by having arrays of JS and files that are dependent on each other, and if they don't load then I have an error state.
I forgot to mention, obviously I am just showing how to create a JS tag, you would have to create your own method for the other types of files you want to load.
Hope maybe that helps, cheers
You can look for the presence of an object in JavaScript, e.g. to see if jQuery is loaded or not...
if (typeof jQuery !== 'function') {
// Was not loaded.
}
jsFiddle.
You could also check for CSS styles missing, for example, if you know a certain CSS file sets the background colour to #000.
if ($('body').css('backgroundColor') !== 'rgb(0, 0, 0)') {
// Was not loaded.
}
jsFiddle.
When these fail, you can make an XHR to the server to log these failings.
What about ServiceWorker? We can use it to intercept all http requests and get response code to log whether the external resource fails to load.
Make a hash of the js name and session cookie and send both js name in plain and the hash. Server side, make the same hash, if both are same log, if not, assume it's abuse.

Categories