What domains/protocols in the img-src directive of the Content-Security-Policy header are required to allow Google AdWords conversion tracking?
From testing, when we call google_trackConversion, it looks like the browser creates an image with a src that follows a chain of 302 redirects between various domains...
www.googleadservices.com ->
googleads.g.doubleclick.net ->
www.google.com ->
www.google.co.uk
The final .co.uk looks suspicious to me. As we're testing from the UK, we're concerned that tracking called from other countries will redirect to other domains.
What is the complete list of domains that we need to open up in order for the tracking to work?
As requested in comments, an example path component of the first request is:
pagead/conversion/979383382/?random=1452934690748&cv=8&fst=1452934690748&num=1&fmt=3&label=jvoMCNP4umIQ1uiA0wM&guid=ON&u_h=1080&u_w=1920&u_ah=1033&u_aw=1920&u_cd=24&u_his=18&u_tz=0&u_java=false&u_nplug=5&u_nmime=7&frm=0&url=https%3A//beta.captevate.com/payment%3Flevel%3Da00&async=1
and repeating the conversion a second time, the path component of the first request is
pagead/conversion/979383382/?random=1452934959209&cv=8&fst=1452934959209&num=1&fmt=3&label=jvoMCNP4umIQ1uiA0wM&guid=ON&u_h=1080&u_w=1920&u_ah=1033&u_aw=1920&u_cd=24&u_his=26&u_tz=0&u_java=false&u_nplug=5&u_nmime=7&frm=0&url=https%3A//beta.captevate.com/payment%3Flevel%3Da00&async=1
I used a free VPN service to connect from a couple of countries (Netherlands and Singapore), and the last redirect doesn't occur: the final request to www.google.com is a 200. However, I obviously haven't tried connected from every country, so my original question stands.
Unfortunately, there aren't many ways around this. Resources require either whitelisting (in the case of remote resources, like this one) or inlining tricks (i.e. nonce or sha256-...) when CSP is active. At the end of the day, though, CSP can probably still make your site safer and protect most resources.
Depending on what you are trying to do, though, you may still be able to achieve your goal.
Here are some options:
Whitelist all images.
Of course, you could simply place a "*" in your img-src directive, but I imagine you already know that and are choosing not to because it defeats CSP's protection for images.
Load the image via alternate means.
If all you are after is specifically locking down images, and, say, don't care so much about XMLHttpRequest, you could load the pixel via POST or even via a <script> tag with a custom type (using the AdWords image tag tracking method). This takes advantage of the fact that Google only needs the browser to complete the HTTP request/response (and redirect) cycle for analytics purposes, and you don't really care about parsing or executing the resulting content, which is a 1x1 transparent pixel anyways. This allows you to lock down your img-src directive (if that is indeed your goal) while still allowing whatever domain Google would like to use for redirects.
I know this only moves your problem, but it's useful if your main threat is malicious images.
Place all Google domains in your img-src.
As suggested below. Header lengths will be a problem (even if the specs say you're fine, implementors are not always so generous), and more importantly, you may encounter spurious failures as Google changes their list of domains, which is certainly not a public or easily noticeable action (besides your ad conversions not coming through!). Since I imagine your job isn't to update that list constantly, you probably don't want to go with this option.
Report failures for a few months and then roll with it.
Because CSP supports reporting URIs and the Content-Security-Policy-Report-Only variant, you can roll it out in report-only mode and wait for reports to come in. If you already have good data about your userbase (and it doesn't change much), this can be a good option - once you see those reports stabilize on a list of domains, seal it in a regular CSP header. Optionally, you can place a reporting URI on the final header to catch any additional failures. The downside of this strategy, of course, is that you don't get protection while in report-only mode, and when you switch to enforcing it, failures cause lost conversion data and you're playing catch up.
Static pixel with reverse proxy
Okay. Well, with the above options not being so great (I admit it), it's time to think outside the box. The problem here is that HTTP optimization techniques applied by Google (sharding/geo-pinning domains) are at odds with good security practice (i.e. CSP). The root cause of the domain ambiguity is the client's geographic location, so why not pin it yourself?
Assuming you have advanced control of your own HTTP server, you could use the static pixel approach for tracking and proxy the request yourself, like so:
User ---> GET http://your-page/
User <--- <html>...
pixel: http://your-page/pixel?some=params
User ---> http://your-page/pixel?some=params
---> fetch http://googleads.g.doubleclick.net/pagead/viewthroughconversion/12345/?some=params
<--- redirect to http://google.com, or http://google.co.uk
User <--- return redirect
Using a static pixel (like approach #2) and putting your proxy, say, in the US or UK should ensure that the source IP is geographically pinned there, and Google's anycast frontend should route you to a stable endpoint. Placing a proxy in between the user and Google also gives you a chance to force-rewrite the redirect if you want to.
To simplify proxy setup (and add some performance spice), you could opt for something like Fastly with Origin Shielding instead of building it yourself. If you add the DoubleClick backend and proxy from there, you can pin the originating requests from the CDN to come only from a certain geographic region. Either way, your user should see a stable set of redirects, and you can trim down that list of Google domains to just img-src 'self' *.google.com *.doubleclick.net *.googleadservices.net.
Edit: It is also worth noting that Fastly (and a growing list of other CDN providers) peer directly with Google Cloud at a few of their Points-of-Presence, offering an optimized path into Google's networks for your proxied traffic.
What are you trying to achieve by locking down your img-src?
CSP is a great security option but most issues are with javascript (which can cause all sorts of issues), css (which can be used to hide or overly elements with injected content) or framing options (which can be used for click-jacking by similarly overlying content). Images are a much smaller risk IMHO.
There are few security risks that I can think of with loading images, which boil down to:
Tracking and the privacy implications of that. Though you are already using Google Adwords which tracks so much. And those that care about this typically block it in their browser.
Loading of insecure content (I presume you are using HTTPS exclusively or this whole conversation is a bit pointless?). This can be remediated with a more loose CSP policy of just https for img-src.
Loading an image and subsequently overlying part of your website with that rogue image. But that requires javascript and/or CSS injection too - which should be locked down in CSP.
Ultimately unless you have a XSS vulnerability people shouldn't be able to easily load images into your pages. And even if they could I think the risks are small.
So, I would be tempted to just have a "img-src 'self' https:;" rather than try any of the other work arounds the others have suggested - all of which have downsides and are not very future proof.
Ultimately if you are that concerned about security of your site that locking down images is a high priority I would question whether you should be running Google Adwords.
However if there is a specific threat you are trying to protect against, while at the same time still allowing Adwords, then provide details of that and there may be other ways around it. At the moment you've asked for a solution to particular problem without necessarily explaining the actual underlying problem which may have solutions other than the one you are asking about.
You can use Wikipedia's List of Google domains. There are many domains unrelated to Google Adwords, but I don't think allowing domains like youtube.com could cause problems.
Currently the list is:
google.com
google.ac
google.ad
google.ae
google.com.af
google.com.ag
google.com.ai
google.al
google.am
google.co.ao
google.com.ar
google.as
google.at
google.com.au
google.az
google.ba
google.com.bd
google.be
google.bf
google.bg
google.com.bh
google.bi
google.bj
google.com.bn
google.com.bo
google.com.br
google.bs
google.bt
google.co.bw
google.by
google.com.bz
google.ca
google.com.kh
google.cc
google.cd
google.cf
google.cat
google.cg
google.ch
google.ci
google.co.ck
google.cl
google.cm
google.cn
g.cn
google.com.co
google.co.cr
google.com.cu
google.cv
google.com.cy
google.cz
google.de
google.dj
google.dk
google.dm
google.com.do
google.dz
google.com.ec
google.ee
google.com.eg
google.es
google.com.et
google.fi
google.com.fj
google.fm
google.fr
google.ga
google.ge
google.gf
google.gg
google.com.gh
google.com.gi
google.gl
google.gm
google.gp
google.gr
google.com.gt
google.gy
google.com.hk
google.hn
google.hr
google.ht
google.hu
google.co.id
google.iq
google.ie
google.co.il
google.im
google.co.in
google.io
google.is
google.it
google.je
google.com.jm
google.jo
google.co.jp
google.co.ke
google.ki
google.kg
google.co.kr
google.com.kw
google.kz
google.la
google.com.lb
google.com.lc
google.li
google.lk
google.co.ls
google.lt
google.lu
google.lv
google.com.ly
google.co.ma
google.md
google.me
google.mg
google.mk
google.ml
google.com.mm
google.mn
google.ms
google.com.mt
google.mu
google.mv
google.mw
google.com.mx
google.com.my
google.co.mz
google.com.na
google.ne
google.com.nf
google.com.ng
google.com.ni
google.nl
google.no
google.com.np
google.nr
google.nu
google.co.nz
google.com.om
google.com.pk
google.com.pa
google.com.pe
google.com.ph
google.pl
google.com.pg
google.pn
google.co.pn
google.com.pr
google.ps
google.pt
google.com.py
google.com.qa
google.ro
google.rs
google.ru
google.rw
google.com.sa
google.com.sb
google.sc
google.se
google.com.sg
google.sh
google.si
google.sk
google.com.sl
google.sn
google.sm
google.so
google.st
google.sr
google.com.sv
google.td
google.tg
google.co.th
google.com.tj
google.tk
google.tl
google.tm
google.to
google.tn
google.com.tr
google.tt
google.com.tw
google.co.tz
google.com.ua
google.co.ug
google.co.uk
google.com
google.com.uy
google.co.uz
google.com.vc
google.co.ve
google.vg
google.co.vi
google.com.vn
google.vu
google.ws
google.co.za
google.co.zm
google.co.zw
admob.com
adsense.com
adwords.com
android.com
blogger.com
blogspot.com
chromium.org
chrome.com
chromebook.com
cobrasearch.com
googlemember.com
googlemembers.com
com.google
feedburner.com
doubleclick.com
igoogle.com
foofle.com
froogle.com
googleanalytics.com
google-analytics.com
googlecode.com
googlesource.com
googledrive.com
googlearth.com
googleearth.com
googlemaps.com
googlepagecreator.com
googlescholar.com
gmail.com
googlemail.com
keyhole.com
madewithcode.com
panoramio.com
picasa.com
sketchup.com
urchin.com
waze.com
youtube.com
youtu.be
yt.be
ytimg.com
youtubeeducation.com
youtube-nocookie.com
like.com
google.org
google.net
466453.com
gooogle.com
gogle.com
ggoogle.com
gogole.com
goolge.com
googel.com
duck.com
googlee.com
googil.com
googlr.com
googl.com
gmodules.com
googleadservices.com
googleapps.com
googleapis.com
goo.gl
googlebot.com
googlecommerce.com
googlesyndication.com
g.co
whatbrowser.org
localhost.com
withgoogle.com
ggpht.com
youtubegaming.com
However, if you want to be sure if that's really all domains, you should ask Google directly.
Unfortunately there is no clean workarround, it only accept wildcards * on the left of the domain.
You can disable this feature on GTM or Universal Analytics but if you do use Google Adds it requires this to calculate the segments to target your add, otherwise your adds will be very expensive (and not targeted)
So: You can check all valid google domains here https://www.google.com/supported_domains
and add them on the white list on img-src and connect-src on your CSP Policy, had cross your fingers that goggle will not add more (youc could monitor this url for changes with any of thee services that does this)
This nightmare ends in mid 2023 when they will deprecate Universal Analytics, GA4 does not use this.
Not sure if you guys are using anything to report the CSP failures, we discovered this service https://report-uri.com/ the free tier gives a reasonable endpoint to report on failures, once we went live we burned our quota in 2 days thought... but it did help to find holes in our CSP.
It did crash our server, we had to increase the HTTP header size once we put twice all google domains
Related
I am developing a web page that needs to display, in an iframe, a report served by another company's SharePoint server. They are fine with this.
The page we're trying to render in the iframe is giving us X-Frame-Options: SAMEORIGIN which causes the browser (at least IE8) to refuse to render the content in a frame.
First, is this something they can control or is it something SharePoint just does by default? If I ask them to turn this off, could they even do it?
Second, can I do something to tell the browser to ignore this http header and just render the frame?
If the 2nd company is happy for you to access their content in an IFrame then they need to take the restriction off - they can do this fairly easily in the IIS config.
There's nothing you can do to circumvent it and anything that does work should get patched quickly in a security hotfix. You can't tell the browser to just render the frame if the source content header says not allowed in frames. That would make it easier for session hijacking.
If the content is GET only you don't post data back then you could get the page server side and proxy the content without the header, but then any post back should get invalidated.
UPDATE: 2019-12-30
It seem that this tool is no longer working! [Request for update!]
UPDATE 2019-01-06: You can bypass X-Frame-Options in an <iframe> using my X-Frame-Bypass Web Component. It extends the IFrame element by using multiple CORS proxies and it was tested in the latest Firefox and Chrome.
You can use it as follows:
(Optional) Include the Custom Elements with Built-in Extends polyfill for Safari:
<script src="https://unpkg.com/#ungap/custom-elements-builtin"></script>
Include the X-Frame-Bypass JS module:
<script type="module" src="x-frame-bypass.js"></script>
Insert the X-Frame-Bypass Custom Element:
<iframe is="x-frame-bypass" src="https://example.org/"></iframe>
The X-Frame-Options header is a security feature enforced at the browser level.
If you have control over your user base (IT dept for corp app), you could try something like a greasemonkey script (if you can a) deploy greasemonkey across everyone and b) deploy your script in a shared way)...
Alternatively, you can proxy their result. Create an endpoint on your server, and have that endpoint open a connection to the target endpoint, and simply funnel traffic backwards.
Yes Fiddler is an option for me:
Open Fiddler menu > Rules > Customize Rules (this effectively edits CustomRules.js).
Find the function OnBeforeResponse
Add the following lines:
oSession.oResponse.headers.Remove("X-Frame-Options");
oSession.oResponse.headers.Add("Access-Control-Allow-Origin", "*");
Remember to save the script!
As for second question - you can use Fiddler filters to set response X-Frame-Options header manually to something like ALLOW-FROM *. But, of course, this trick will work only for you - other users still won't be able to see iframe content(if they not do the same).
Would it be possible to load an external page inside a container and replace text elements?
We work with ad campaigns and earn a percentage whenever a user signs up.
Can a script replace certain words? For instance “User” to “Usuario” or “Password” to “Contraseña” without affecting the original website or its functions.
Note: These links always pass through a redirection.
Example:
http://a2g-secure.com/?E=/0yTeQmWHoKOlN6zUciCXQwUzfnVGPGN&s1=
Note 2: Using an iframe is out of the question due to “Same-origin policy”.
I'm not sure if this answers your question, but you might find it useful.
(Perhaps you might give a step-by-step example of what you're trying to accomplish?)
If we assume that a browser attempts to retrieve page P from a proxy which first retrieves the content of page P from its actual home and then performs some transformation on its content before returning that page content to the browser, what you're describing is a Reverse HTTP Proxy and is a very well-known page serving technique.
Rather than performing complex transformations at the server (which require specialized knowledge of the page layout), this technique is usually used to inject a single line into the retrieved source that calls a JavaScript file to actually perform the required transformation at the browser.
So in essence:
Browser requests Page P from Proxy 1.
Proxy 1 retrieves the actual Page P from its real home, Server 2.
Proxy 1 adds the line <script src="//proxy1.com/transform.js"></script> to the source of Page P.
Proxy 1 then returns the modified source of Page P to Browser.
Once the Browser has received the page content, the JavaScript file is also retrieved, which can then modify the page contents in any way required.
This technique can be used to solve your "Same origin policy" issue by loading an iframe from a URL that points to the same server as that which provided the parent or owning page of the iframe which acts as proxy, like:
http://example.com/?proxy_target=//server2.com/pageP.html
Thus, the browser only "sees" content from a single server.
You would need to load the external page server-side, and then you can do whatever you want with it. You can do serverside string replacement, or you can do it later in javascript.
But, remember that as soon as you add a whole webpage into for example a div in your own page, the css from your page will affect it.
Plus, you would need to manipulate all the links in the documents, to have absolute urls. If the page depends on ajax, there is pretty much no way to accomplish what you want to do.
If on the other hand the pages you will be loading are static html, it is possible, though there are a lot of things you need to take care of before you can actually present the page to the user, like adjusting links, urls to stylesheets and so on.
It seems you are trying to localize a website on the fly, using your server as a proxy for that content. Does it make sense? If that's the case, depending on the size of your operation, there are several proxy translation services out there (I'll name them if needed).
Basically, they scrape a website, providing a way for you to translate and host the translated content. Of course, this depends on your relationship with the content providers. You should also take this into consideration, since modifying content, even for translation, can be a copyright problem.
All things considered, if you trust the provider's javascript, the solution involves scraping the content, as mentioned in other answers, and serving that modified content. You really need to trust the origin...
update per request
http://www.easyling.com
http://www.smartling.com
http://www.motionpoint.com
http://www.lionbridge.com/solutions/translation-proxy/
http://www.sajan.com/translation-proxy-technology-and-traditional-website-translation-understanding-your-options/
They are all aimed at enterprise-grade projects, but I would say Easyling is the most accessible.
Hope this helps.
Using the .load() callback function, this will replace the text
$(function(){
$("#Content").load("http://example.com?user=Usuario",function() {
$(this).html($(this).html().replace("user", +get param value+));
});
redirection u can use
// similar behavior as an HTTP redirect
window.location.replace("url");
// similar behavior as clicking on a link
window.location.href = "url";
The answer is NO, not without using a server-side proxy. For a really good overview of how to use a proxy, see this YUI page: https://developer.yahoo.com/javascript/howto-proxy.html (Be patient, as it will take time to load, but the illustrations are worth it!)
When I try to do this in jsfiddle to see what data that the 3 parameters contain, then the error below appears:
$(function() {
$(this).load('https://stackoverflow.com/questions/36003367/load-external-page-and-replace-text', function(responseText, textStatus, jqXHR){
debugger;
});
});
ERROR:
XMLHttpRequest cannot load Load external page and Replace text.
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://fiddle.jshell.net' is therefore not allowed access.
I'm building a Chrome extension and using the db.js wrapper to utilize the indexeddb. The problem is, I've got several subdomains and I'd like to be able to share the information across them.
When I use the Chrome Dev tools to view Resources, all of the individual subdomains have their own copy of the schema I'm creating, and each has it's own data.
The only thing I knew to try was to set the document.domain but that didn't help. I wasn't surprised.
Documentation on indexeddb is very slim it seems. I keep finding the same 2 or 3 blog posts copied word for word in several different blogs and nothing specifies that this is possible or impossible.
You can't access the same database from multiple subdomains, the access scope is limited to html origin.
html_Origin = protocol + "://" + hostname + ":" + port + "/";
As #Xan mentioned, if you can use a common origin owned by the extension itself, rather than by the content pages, that sounds like it would be by far the easiest solution. If for whatever reason you can't do that (or for readers who got here wanting to know about regular page javascript or Greasemonkey-style userscripts, rather than extensions), the answer is:
Yes, though it's a slightly awkward and takes some work:
Since you're using a number of related subdomains, (rather than completely unrelated domains), there's a technique you can use in that situation. It can be applied to IndexedDB, localStorage, SharedWorker, BroadcastChannel, etc, all of which offer shared functionality between same-origin pages, but for some reason don't respect modifications to document.domain.
(1) Pick one "main" subdomain to for the data to belong to. i.e. if your subdomains are https://a.example.com, https://b.example.com, and https://c.example.com, you might choose to have your IndexedDB database stored under the https://a.example.com subdomain.
(2) Use it normally from all the the https://a.example.com pages.
(3) On https://b.example.com and https://c.example.com, use javascript to set document.domain = "example.com";. Then also create a hidden <iframe>, and navigate it to some page on the https://a.example.com domain (It doesn't matter what page, as long as you can insert a very little snippet of javascript on there. If you're creating the site, just make an empty page specifically for this purpose. If you're writing an extension or a userscript and so don't have any control over pages on the example.com server, just pick the most lightweight page you can find and insert your script into it. Some kind of "not found" page would probably be fine).
(4) The script on the hidden iframe page need only (a) set document.domain = "example.com";, and (b) notify the parent window when this is done. After that, the parent window can access the iframe window and all its objects without restriction! So the minimal iframe page is something like:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
If writing a userscript, you might not want to add externally-accessible functions such as iframeReady() to your unsafeWindow, so instead a better way to notify the main window userscript might be to use a custom event:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Which you'd detect by adding a listener for the custom "iframeReady" event to your main page's window.
(5) Once the hidden iframe has informed its parent window that it's ready, script in the parent window can just use iframe.contentWindow.indexedDB, iframe.contentWindow.localStorage, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorker instead of window.indexedDB, window.localStorage etc. ...and all these objects will be scoped to the https://a.example.com origin - so they'll have the this same shared origin for all of your pages!
The "awkward" part of this technique is mostly that you have to wait for the iframe to load before proceeding. So you can't just blithely initialize IndexedDB in your DOMContentLoaded handler, for example. Also you might want to add some error handling to detect if the hidden iframe fails to load correctly.
Obviously, you should also make sure the hidden iframe is not removed or navigated during the lifetime of your page... OTOH I don't know what the result of that would be, but very likely bad things would happen.
And, a caveat: setting/changing document.domain can be blocked using the Feature-Policy header, in which case this technique will not be usable as described.
However, there is a significantly more-complicated generalization of this technique, that can't be blocked by Feature-Policy, and that also allows entirely unrelated domains to share data, communications, and shared workers (i.e. not just subdomains off a common superdomain). #Xan alludes to it in point (2) of his answer:
The general idea is that, just as above, you create a hidden iframe to provide the correct origin for access; but instead of then just grabbing the iframe window's properties directly, you use script inside the iframe to do all of the work, and you communicate between the iframe and your main window only using postMessage() and addEventListener("message",...).
This works because postMessage() can be used even between different-origin windows. But it's also significantly more complicated because you have to pass everything through some kind of messaging infrastructure that you create between the iframe and the main window, rather than (for example) just using the IndexedDB API directly in your main window's code.
HTML-based storage (indexedDB, localStorage) in Chrome extensions behaves in a way that might not be expected, but it's perfectly natural.
In the background page, the domain is chrome-extension://yourextensionid/, and this is shared by all extension pages and is persistent.
In the content scripts though, you're sharing the HTML storage with the domain you're operating on. This makes life difficult if you want it to share/persist things. Note that sometimes this behavior is actually helpful.
The universal solution is to keep the DB in a background script, and communicate data/requests by means of Messaging API.
This was the usual solution for localStorage use until chrome.storage came along. But since you're using a database, you don't have a ready extension-friendly replacement.
I have a large website that is using two large online advertisement "Remnant" providers. These providers are such that they start and stop ad campaigns on a regular basis that run on our website.
One of the ads coming from one of the providers is incorrectly making a request to:
/eyeblaster/addineyev2.html
I have determined that the file being requested is used by some websites when the ads on the website are served via iframes. This file in theory would circumvent the cross domain restrictions so that the ad provider could resize the iframe using javascript within the iframe.
I determined this use of the file by stumbling upon this support document:
http://support.google.com/dfp_premium/bin/answer.py?hl=en&answer=1085693
My problem is that our websites do not use iframes to deliver advertisements, so the requests going to the "/eyeblaster/addineyev2.html" URI results in a 404 error, and is unnecessary. Because the error is coming from a large vendor-provided CMS the error renders with our Google Analytics tracking code on it. This has the result of inflating our apparent pageviews.
The pageview inflation can be very severe, because the 404 error page also contains ads. That 404 page could also load the faulty ad, resulting in a recursive loop of ads loading the exact same "/eyeblaster/addineyev2.html" 404 page.
I have thus far been unable to witness an ad making a direct request to this url via Firebug or similar developer tools. Yet, the traffic to this non-existent page is gigantic so the offending ad is certainly still in the mix. The problem is that I cannot figure out which ad is broken, so I can't tell our remnant providers to remove it. Both vendors are feigning ignorance of the issue.
I cannot remove the Google tracking code on the 404 error page, but I can add additional JavaScript to the page.
Is there any way that I could identify the ad causing a request to "/eyeblaster/addineyev2.html" by adding some javascript to the 404 error that results when trying to request that page inside an iframe?
Essentially almost a "frame buster" script that instead of busting the frame, gives information on the HTML nodes nearby the iframe element? I think it's mildly possible, but I'm not seeing a clear path at the moment.
Thanks!
To avoid that unwanted tracking you should place a dummy empty file on /eyeblaster/addineyev2.html, or, if you use nginx do something like
server {
...
location = /eyeblaster/addineyeV2.html { echo ""; }
}
or, better
server {
...
location = /eyeblaster/addineyeV2.html { return 404 "404 - page not found";}
}
If you don`t have static hosting and cannot configure a proxy server you can put a condition in your 404 page tracking via javascript
if (document.URL.indexOf('/eyeblaster/addineyeV2.html') == -1) {
doAnalyticsTracking();
}
I have found my own answer, and I'll share it here for the rare event another Web Developer is trying in vain to pinpoint an ad doing this same thing to them.
The offending digital ad was coming in with an iframe that was pointed toward "/eyeblaster/addineyev2.html" I used this knowledge, and coded the following javascript to gather information about the page that contained the iframe (ie the page with the ad on it).
if(top != self) {
$.post("/ad_diagnose/log.php", {
a: $('#ad-div-one', top.document).html(),
b: $('#ad-div-two', top.document).html(),
c: $('#ad-div-three', top.document).html(),
d: $('#ad-div-four', top.document).html(),
e: $('#ad-div-five', top.document).html(),
});
}
This JavaScript uses JQuery (which our CMS provider includes on every page anyway). It checks to see if the error page exists in an iframe (top != self), and then it grabs the raw html for every html element on the parent page that should contain an ad.
That data is wrapped into an object, and posted to a simple php script that would write a log of every value posted to it to a file.
In the end, I received a log file with a high likelihood that the offending ad code was within. I was able to do a quick grep on the file and discovered the ad with an iframe pointing toward "/eyeblaster/addineyev2.html"
I hope this helps someone else out there!
It looks like there are more publishers having this issue. I do too. Following Tals instructions I was able to log information when pointing an iframe to a 404-page on purpose, but wasn't able to catch this problem as it appears randomly and I can't check why the script is not catching it.
How about adding /eyeblaster/addineyev2.html and log from this file?
I was able to determine the owner of the script doing a simple web search. It is coming from http://www.mediamind.com/
But disabling "mediamind" in Google AdSense doesn't do the trick, so I asked their support to send me the file.
I am going to test the script and if 404-calls are getting lower. Maybe I will also use the script to check for the content being loaded and determine the exect ad url to shut it down.
Just thought I would share that this is happening over at our Ozzu website as well. I was first aware of the issue when some of our members were complaining, but I didn't look too deeply as I first thought it was an isolated instance.
Over the past month I have also noticed that my error log files on the server have been higher than normal pushing the /usr partition to around 82% of its usage. I didn't put two and two together until today as I finally started looking through the errors and it appears that this is not an isolated instance with this eyeblaster type ads. There are many thousands of users coming to our site and then getting redirected to a 404 page on our website because of this. Here is a sample of one of the errors in our log file, and it appears that numerous networks are using this eyeblaster software from Media Mind:
[Thu Dec 13 16:36:51 2012] [error] [client 123.123.123.123] File does not exist: /public_html/eyeblaster, referer: http://lax1.ib.adnxs.com/if?enc=AAAAAAAAAAAAAAAAAAAAAAAAAGC4Hvs_AAAAAAAAAAAAAAAAAAAAAMqchzp-qp9L_vlliXOoLV2gdMpQAAAAAEMUDABGAQAAQAEAAAIAAADXo0AA-FcCAAAAAQBVU0QAVVNEAKAAWAIAeAAAYk4AAgMCAQUAAIIA5BXJnQAAAAA.&cnd=%21QxtEWwidpzIQ18eCAhgAIPivCTAEOIDwBUABSMACUMOoMFgAYL4FaABwKngAgAH6AYgBAJABAZgBAaABAqgBALABALkBAAAAAAAAAADBAQAAAAAAAAAAyQEgEFk1j_LCP9kBAAAAAAAA8D_gAQA.&udj=uf%28%27a%27%2C+15986%2C+1355445408%29%3Buf%28%27c%27%2C+824221%2C+1355445408%29%3Buf%28%27r%27%2C+4236247%2C+1355445408%29%3B&ccd=%21mgWjMAidpzIQ18eCAhj4rwkgAQ..&vpid=18&referrer=http%3A%2F%2Fwww.ozzu.com%2F&dlo=1
[Thu Dec 13 16:36:56 2012] [error] [client 123.123.123.123] File does not exist: /public_html/eyeblaster
I have just contacted the Media Mind company as well to see if they have any further input. The errors in our logs are at least coming from a few ad servers such as:
lax1.ib.adnxs.com
showads.pubmatic.com
ad.yieldmanager.com
So it is my impression that numerous Media companies are using this Eye Blaster software. I looked more into what Eye Blaster supposedly does, and it is some sort of technology that syncs numerous ads on the page as if they are one big ad. For instance an animation will start in one ad and end in another. Anyway it must be popular as numerous ad companies seem to be using it and as such I would probably have to disabled alot of advertisers.
I think the best way to fix the problem would be to have Media Mind address it, but I am not sure.
Anyway just wanted to share my experience and that this problem seems to be affecting numerous websites.
I'm using Google Maps JS API v3 for a project. Is there a way to ask the map to cache tiles on the client's machine so that when they refresh the browser, the tiles don't have to all download again?
Many of my clients are on cellular connections where redownloading the map takes a considerable amount of time.
Thanks!
By default google maps return's cached images (you can see this in the network tab of the console).
If you user's having trouble caching the images, it's probably because they disabled the cache
This is actually possible with HTML5 and its cache-manifest feature. I'd suggest this question (and answer) be updated.
Google coders themselves have tackled this problem and unfortunately the information isn't well disseminated.
Required Readings
First take a look at the Google Code blogpost here: http://googlecode.blogspot.com/2010/04/google-apis-html5-new-era-of-mobile.html
Then have a read at Missouri State's own post: http://blogs.missouristate.edu/web/2010/05/12/google-maps-api-v3-developing-for-mobile-devices/
The Technique
You must cache every URL used by Google Maps
Employ methods to battle Chrome's and Firefox's stubborn caching methods by removing it from "offline websites"
All customizations must be client-side in javascript
Your cache file will look like (as per Missouri State):
CACHE MANIFEST
/map/mobile/examples/template.aspx
/map/mobile/examples/template.css
/map/mobile/examples/template.js
NETWORK:
http://maps.gstatic.com/
http://maps.google.com/
http://maps.googleapis.com/
http://mt0.googleapis.com/
http://mt1.googleapis.com/
http://mt2.googleapis.com/
http://mt3.googleapis.com/
http://khm0.googleapis.com/
http://khm1.googleapis.com/
http://cbk0.googleapis.com/
http://cbk1.googleapis.com/
http://www.google-analytics.com/
http://gg.google.com/
Caveats
You will need to be entirely HTML5-based and recognize the impacts this will have on your users. This situation is handy where either your users are up-to-date on browser standards/devices or you have control over user choices.
Hope this helps.
The previous answer re the cache-manifest feature is incorrect. If you read the spec at http://www.w3.org/TR/html5/offline.html, under "5.7.3 The cache manifest syntax" you'll see that the NETWORK section of the manifest file actually lists resources that should NOT be cached:
# here is a file for the online whitelist -- it isn't cached, and
# references to this file will bypass the cache, always hitting the
# network (or trying to, if the user is offline).
NETWORK:
comm.cgi
The previous poster's example is actually saying:
1) cache the following files:
/map/mobile/examples/template.aspx
/map/mobile/examples/template.css
/map/mobile/examples/template.js
2) fetch the following from the network:
http://maps.gstatic.com/
http://maps.google.com/
http://maps.googleapis.com/
http://mt0.googleapis.com/
http://mt1.googleapis.com/
http://mt2.googleapis.com/
http://mt3.googleapis.com/
http://khm0.googleapis.com/
http://khm1.googleapis.com/
http://cbk0.googleapis.com/
http://cbk1.googleapis.com/
http://www.google-analytics.com/
http://gg.google.com/