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.
Related
I have the following situation:
a static site, only html pages
a cookie notice system, with my own cookies, accept and refuse system of cookies setup
Now I need to inject the GA4 script into the head of pages when cookies are accepted, but...
I have already made made that, by appending the script to the head and it is visible on browser, on page reload with inspect elements...and it's working perfect.
When users click on accept cookies, the cookies accept is saved on client's side, and the script is APPENDED to page.
But I need the GA4 script to be somehow INJECTED, to be visible on the source page. Like when I preview the source page in browser to have it there. I don't need it to be injected into the html file itself, but only into the browser.
I did my own research about these days, and now it's killing me, as all I could find was the append way, but that is not injecting it into the source page on browser.
Any advice or guidance would be greatly appreciated.
Note (as I have been asking all the time. I don't want to offend anyone, but that's the best way I can explain where I want to do and what):
the source page I'm talking about is when right click on browser and view source page (there is where I need the GA4 code to be inserted)
and the way I got it to work is when right click > inspect > elements tab - (there i have it now working)
Thank you!
First question would be, why do you want it to be in the actual source code? A common way of inserting these scripts is through a tag-management-solution, which basically follows similar logic as appending scripts to the page (i.e. similar to what you meant by the inspect elements route).
To answer your question;
There is an option to get it into the sourcecode, and that is by checking on the server delivering the HTML whether a user has accepted the cookies, if that is the case deliver the HTML file (or adjust the HTML) to contain the GA4 script, if the user didn't accept: deliver the page without the GA4 script.
Since you mention these are static HTML files, I assume there is no server in place where this kind of logic can be inserted. So the best option is to insert the script afterwards.
Another way would be to insert the tag by default, but disable tracking (haven't tested the below part, also, verify yourself whether in your situation this actually blocks tracking when cookies aren't accepted):
window['ga-disable-GA_MEASUREMENT_ID'] = true;
https://developers.google.com/analytics/devguides/collection/gtagjs/user-opt-out
You could try to add this in your HTML before loading the GA4 tag, similar to something like:
<script>
const gaMeasurementId = 'G-12345678'; //replace with your own MeasurementID
let cookiesDeclined = true; //default to declined cookies
document.cookie.split(';').forEach( (cookie) =>{ //loop through all cookies
const cookie_arr = cookie.split('='); //get key/value pairs for cookies
let name = cookie_arr[0]; //cookiename
let val = cookie_arr[1]; //cookieval
if(name === 'cookieConsent' && val === 'accepted' ){
cookiesDeclined = false; //set the declined status to false when user has accepted the cookies
}
})
window['ga-disable-'+gaMeasurementId] = cookiesDeclined;
//->insert ga4 tag here
</script>
Heyo,
I'm trying to create a script that opens a URL and sign in using the given credentials.
Therefore I created this:
window.open("https://stackoverflow.com/users/login");
document.getElementById('email').value = "ThisIsMy#Email.com";
document.getElementById('password').value = "ThisIsMyPassword";
document.getElementById('submit-button').click();
But then I changed the code to wait for the page to load using window.onload:
window.open("https://stackoverflow.com/users/login");
window.onload = function() {
document.getElementById('email').value = "ThisIsMy#Email.com";
document.getElementById('password').value = "ThisIsMyPassword";
document.getElementById('submit-button').click();
}
However, this does not seem to work.
Therefore I added some console.log into my code to debug, like this:
console.log("starting")
window.open("https://stackoverflow.com/users/login");
console.log("page open")
window.onload = function() {
console.log("page loaded")
document.getElementById('email').value = "ThisIsMy#Email.com";
document.getElementById('password').value = "ThisIsMyPassword";
document.getElementById('submit-button').click();
console.log("signed in")
}
When I run the code in the console (Chrome/Firefox), I get back started and page open, but nothing else.
When I test the function isolated (i.e. the 3 different document.getElementById) it works just fine. Something must be wrong with the window.onload call?
From other sources here on StackOverflow I tried to use document.onload instead, and I also tried to use document.addEventListener('DOMContentLoaded', function() {...}, but none of these seems to be working either.
Does anyone have any suggestions?
#newbie
You simply can't access a cross origin page. What you are trying is only available to browser addons. And addons also require a specific permission granted by the user. For example the chrome permission to modify a webRequest: https://developer.chrome.com/docs/extensions/reference/webRequest/
window.open() returns the child window and this can be accessed IF it is about:blank or if the same-origin-rule applies (protocol, hostname and port - see pic below). Take a look at this fiddle it shows something similar to what you are trying. (CORS 1)
Here you can see which child windows you may have access to. This means modify it on the fly or override it's content/location completly.
The only method to communicate between two pages is: window.postMessage() and the window: Message-Event which provides an easy to use API for communication.
in your html page, in the script tag, where you call to your js page, add defer. like this:
<script src="your_script.js" defer></script>
I would like to remind you it is not a very good idea to use password credentials inside javascript since it is hard to protect from public appearance.
I believe you can solve this kind of problem with programs such as Python, C++ , maybe Java , but Javascript is a Client-Side program which has some limitations but if you ask me these limitations actually makes it quite fun to use most of the time.
I am loading a remote page with an iframe in node-webkit app.
I would like to run a function from the node.js app from the webpage.
In app.js i have
var xxx = function(){ console.log('test'); }
and in http://www.test.com/index.html i have tried:
window.xxx();
xxx();
global.xxx();
But nothing seems to work.
How can i do that?
Many thanks
If I understand correctly, you want to access a function that's defined in the remote page that you are including as an iframe in your current page, right?
There are two separate issue here, I think.
First, you need to have a handle on the iframe, then access that window's environment through the 'contentWindow' property of the iframe dom element, i.e. given an iframe with id foo, that points to a page with a function named bar, you could do this:
x = document.getElementById('foo');
x.bar();
This works fine for me with a local page, but the other issue is that you might find some difficulty with running a remote page in an iframe and still having access. If it's a page under your control, that might work, but some pages don't like to be run in iframes, so then you have to sandbox to some extent, which may interfere with your ability to access it in this way. It's been a while since I played with sandboxing, so I'm not sure, but if it's a page you control, you should be able to set it up so it's not a problem.
I would like to grab an element from a remote HTML page. As I am requesting data from a different domain I am using the below code to add the source as a script. Yes, very dodgy.
<script type="text/javascript">
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'http://remoteDomain.com/page.html');
document.getElementsByTagName('head')[0].appendChild(script);
</script>
The above code fetches and appends the entire page to my document head. Seems to work okay. However now I would like to able to grab an element by ID, or even regex from this source.
Can this be done?
I am aware that the above code is dirty, so I'd be happy to receive any suggestions to clean it up!
Indeed very dodgy... But there are crossdomain AJAX tehniques that you can use. Some help here: http://usejquery.com/posts/9/the-jquery-cross-domain-ajax-guide
The above code fetches and appends the entire page to my document head.
It doesn't really, it just creates a script element of which its src points there.
It looks like you are trying to get around Same Origin Policy.
Can you use a server side proxy?
Browsers go to great lengths to prevent this being done client-side unless the site you're trying to read explicitly opts in.
Otherwise any random web page you visit could read info from your bank account, say.
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