0

I have an ad that displays within an iframe on a given publisher site around every 1000 loads or so. I have no control over the host site but I need a way to see the ad live as users will see it. I'm trying to figure out a javascript solution that will load the page, search for the name of my company to see if my ad loaded (the company name is the id of a div tag that loads the iframe) and then either stop there if it finds it, or reload the page if not.

I had it sort of working by running a script in the console that got the innerHTML of the document body, searched for a keyword and then reloaded the page if the keyword wasn't found.

Two problems though.

  • It could only find keywords outside of the iframe.
  • It didn't search the content of the iframe (where the actual keyword that would identify my particular ad sits) even if I set a delay or did onload.

Secondly, for every page refresh, the script would be cleared from the console.

I know this is beginner stuff but I would love any pointers to the correct way to tackle this problem.


Thanks so much for the help thus far (also, I upvoted everyone but don't think I have the necessary cred for it to show up publicly)

Here's where I got. I created a chrome plugin with the following manifest.json:

{
  "manifest_version": 2,
  "name": "Ad Refresh",
  "version": "1.0",

  "permissions": [
    "activeTab",
    "tabs"
  ],

  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "js": ["jquery.min.js", "contentscript.js"],
      "all_frames": true
    }
  ]  
}

I have the content-scripts running on all urls but will restrict it once I get things running properly.

For contentscript.js that gets injected and runs in each frame, I have:

setTimeout(function(){

    $("[title='3rd party ad content']").attr("id", "dfp"); // "3rd party ad content" is the title of all iframes that could potentially contain my ad and is the only identifying attribute across all iframe instances.  I stick an id on there so it's easier to grab with getElementById.  It only gets the first instance though, need to figure out how to loop through all.

    var company = document.getElementById('dfp');

    if (company == null) {
      console.log("no hit");
    } else {
      console.log(company);
    }
}, 5000);

I'm not worried about reloading the page, I'm just stuck on getting access within the iframe.

I am unable to directly grab any element within the actual content of the iframe with jquery $ or getElementById etc. However, if I run getElementId on the iframe itself and console.log it, it includes all the HTML inside the iframe:

http://i.stack.imgur.com/dfuYt.png

I tried getting the innerHTML of the iframe element so that I'd have it as a string and could search for it, but all it returns is the iframe element tags, none of the inner content. I don't know if any of that makes sense but I appear to be over my head at this point.


Ok, last addition. My ad runs a script that I can see under "Sources" in inspector. So I thought "Why not run var scripts = document.getElementsByTagName('script'); to get an array of all the scripts that were loaded on the page? Then I could just search the array to see if my script and hence my ad had loaded and we'd be golden." Unfortunately though, it doesn't include my script in the array, even when it's loaded and is visible in "Sources" and accurately includes a random Stripe script that's also loading from within an iframe. Bummer...

Diriector_Doc
  • 416
  • 1
  • 10
  • 24
greenleaf
  • 21
  • 2

3 Answers3

0

Use .load event of the jQuery to know whether iFrame is loaded and then read the innerHTML of the iframe body

Try this:

$('#ID_OF_THE_IFRAME').load(function() {
  var iFrameContent = $('body', this.contentWindow.document).html();
  console.log(iFrameContent);
});
Rayon
  • 34,175
  • 4
  • 40
  • 65
0

Fiddle

JS:

    var company = document.getElementById('myframe1').contentWindow.document.getElementById('company');
if (company == null) {
  //reload
  console.log("reload");
} else {
  //continue
  console.log(company);
}
Dipali Vasani
  • 2,268
  • 2
  • 13
  • 29
0

It sounds like the iframe containing the ad is loaded from a different domain than the main page, is that right? That would explain why your JavaScript code running in the main page (or in the console, same thing) can't access DOM elements inside the iframe. Browser cross-domain security prevents that kind of access: the iframe is treated just like a separate browser window or tab.

If the main page and the iframe were both loaded from the same domain, then you could use contentWindow as a couple of answers have described. But that won't work across domains.

So, what can you do?

You're building a tool for your own use or the use of your colleagues - not something you need to publish on a website for the rest of the world to use, right?

This gives you a couple of other options. First, you could simply disable cross-domain browser security. In Chrome, you can do that as described here:

Disable same origin policy in Chrome

Beware: Don't do any "normal" browsing in a Chrome session running in this mode, only your special testing. But if you do run Chrome in this mode, then you'll be able to access iframe DOM elements via contentWindow and contentWindow.document as described in the other answers.

If that doesn't do the trick, or if you don't want to have to start a special Chrome session for this, another approach would be to write a Chrome extension. This would allow you to write code to access DOM elements in both the iframe and the main window using techniques like these:

access iframe content from a chrome's extension content script

Chrome extension to remove DOM elements inside iframes

Or you could write a Firefox extension if you prefer - similar capabilities are available in both.

Community
  • 1
  • 1
Michael Geary
  • 26,814
  • 8
  • 56
  • 71
  • Thanks to everyone for the help! Your assumptions are correct that this is a tool for personal use and that the iframe is loading content from another domain. I wrote a chrome extension and used the content_scripts with all_frames : true method but still haven't been able to get access to the full content of the iframes. When I log the innerHTML it gives me the iframe element itself but none of the contents inside of it :( Will keep trying. – greenleaf Mar 07 '16 at 23:30