Injecting HTML into existing web pages - javascript

I'm interested in the concept of injecting a bit of HTML into existing web pages to perform a service. The idea is to create an improved bookmarking system - but I digress, the specific implementation is unimportant. I'm quite new to web development and so I have no definite idea as to how to accomplish this, thought I have noticed a couple of possibilities.
I found out I can right click > 'inspect element' and proceed to edit my browser's version of the HTML corresponding with the webpage I'm viewing. I assume that this means I can edit what I see and interact with. Could I possibly create a script that ran from a button on bookmarks bar that injected an Iframe which linked to a web service of my making? (And deleted itself after being used).
Could I possibly use a chrome extension to accomplish this? I have no experience with creating extensions and so I have no clue what they're capable of - though I wouldn't be against learning.
Which of these would be best? If they are even valid ideas. Or is there another way that I've yet to know of?
EDIT: The goal is to have a user click a button in the browser if they would like to save this page. They are then presented an interface visually independent of the rest of the page that allows them to categorize this webpage according to their interests. It would take the current link, add some information such as a comment, rating, etc. and add it to the user's data. This is meant as a sort of side-service to a website whose purpose would be to better organize and display the browsing information of the user.

Yes, you can absolutely do this. You're asking about Bookmarklets.
A bookmarklet is just a bookmark where the URL is a piece of JavaScript instead of a URL. They are very simple, yet can be capable of doing anything to a web page. Full JavaScript access.
A bookmarklet can be engaged on any web page -- the user simply has to click the bookmark(let) to launch it on the current page.
Bookmark = "http://chasemoskal.com/"
Bookmarklet = "javascript:(function(){ alert('I can do anything!') })();"
That's all it is. You can create a bookmarklet link which can be clicked-and-dragged onto a bookmark bar like this:
Bookmarklet
Bookmarklets can be limited in size, however, you can load an entire external script from the bookmarklet.

You can do what you refer to as like an <iframe>, so here are some steps that may help you, simply put:
Create an XMLHttpRequest object and make a request for a page trough it.
Make the innerHTML field of an element to hold the resultString of the previous request, aka the HTML structure.
Lets assume you have an element with the id="Result" on your html. The request goes like this:
var req = new XMLHttpRequest();
req.open('GET', 'http://example.com/mydocument.html', true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4 && req.status == 200) {
Result.innerHTML = req.responseText;
}
};
req.send(null);
Here's an improved version in the form of a fiddle.
When you're done, you can delete that injected HTML by simply:
Result.innerHTML = '';
And then anything inside it will be gone.
However, you can't make request to other servers due to request policies. They have to be under the same domain or server. Take a look at this: Using XMLHttpRequest on MDN reference pages for more information.

Related

inject GA4 script in the html of a static site with javascript

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>

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.

Remove target attribute in iframe link

I have an iframe on one of my pages that shows content on an external site (vendor product). All works well except a few links that have target="_main" in them. These links open in a new tab. What I need to do is strip the target attribute from all links within the iframe so all links stay within the iframe rather than opening a new window or tab.
It seems like there should be a simple javascript solution to this.
If I can't get this to work in an iframe then I will be forced to re-create all the content on my site which would be very painful..... to say the least.
Any help???
You need access to the external site's codebase in order to dynamically fix this. What you want to do in the external site's codebase is to check if the sites is within an iframe. If it is within an iframe then run a function to remove all target attributes on links.
// vendors product page
if ( self !== top ){
$('a').removeAttr('target');
} // else do nothing
self !== top is the same as saying if my site isn't the top most window then return true.
Not directly that I am aware of.
However, if you have access to a scripting language (like PHP or ASP) on your site you can read your vendors' page directly from your server, do a find & replace on it & then render that onto your site; either in an iframe or however else you want.
Edit
There are many ways to do this, depending on how much control you have over you PHP config. Have a look at these resources & see if you can figure out what to do. If not I would suggest you start a new question specifically focused on what it is you are struggling with.
http://php.net/manual/en/function.file-get-contents.php With this method you have to be aware of the tip on the page:
A URL can be used as a filename with this function if the fopen wrappers have been enabled. See fopen() for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide.
http://php.net/manual/en/function.fsockopen.php Again, be aware of the warning & notes.
http://php.net/manual/en/book.curl.php
I personally have written a class that uses fsockopen because it is the most flexible for my needs but usually file_get_contents does the trick because it is the simplest to set up out of the 3 options, if you have the right wrappers configured & you don't need to start working with SSL or funny protocols. I stay away from CURL because you have to install a library in order for it to work. I prefer my code to be portable for standard installs.
Some useful links that might help:
PHP readfile from external server
Possible Example
$vendorUrl = isset( $_REQUEST['vendor'] ) ? $_REQUEST['vendor'] : 'www.default-vendor.com';
$iframeContents = file_get_contents("http://$vendorUrl", false);
exit str_replace( 'target="_main"', '', $iframeContents );
Then you just have point your iframe at whatever page you save this script in on your server & include ?vender=www.vendor-url.com as the query string.
How about giving your own iframe the name _main?
<iframe name="_main" ...
The other links should then open in that iframe too.
Regards, Max

How to get url of embedding page for a javascript widget

(Rewording the question as there were very few views otherwise).
I want to build a widget that others can include on their website, and the widget itself will be hosted on my website. I am aware of just one method to build widgets that can be embedded on other websites: The website that wants to embedd the widget sources a javascript from my site, which does "document.write" on the page. Something like:
<script language="javascript" src="http://www.my-website-that-will-host-the-widget.com/javascript-emitter.php?id=1234&width=200&bordercolor=000000&bg=ffffff&textcolor=000000"></script>
Now, I want to make a particular widget accessible from only particular domains. For this, I want to know the URL of the page that is embedding my widget reliably . No-one should be able to spoof it. For example, if I have an explicit variable in the embedding code, people can change it.
How do I do it? (I also want that there minimal code to write for the person who is embedding my widget).
regards,
JP
Explanation 1:
Lets say I want to do this: If widget is accessed from 1.com, display A, else display B. How do I do it reliably. Thing is, "A" is something that should not be visible in the code unless the widget is accessed from 1.com. (Thus, if it is embedded in 2.com, I don't want to output if(location.href == 1.com) write(A) else write (B)
Note 1:
(As an aside, if someone feels my method is not good/efficient and can suggest better methods/tutorials, etc., that would be great help. Most google queries give you sites that explain how to build/obtain widget for "your site".... and usually point to websites that allow you to build widgets hosted with them, I want to understand how to build widgets that can be embedded by other websites from my site)
In javascript on the client-side, you can use location.href to get the url of the current page:
var url = location.href;
If you do not want to output any javascript at all for a forbidden domain, in your php you can check the HTTP_REFERER header with the global variable $HTTP_REFERER. In your javascript-emitter.php script try this:
<?php
echo $HTTP_REFERER;
?>
However be warned that this is not always to be trusted: it is up to the client (the browser) to send the correct REFERER header. And of course if someone really wanted to include your widget on their site, they could easily request your javascript server-side spoofing the REFERER header - that is set it to something that's on your whitelist - before forwarding it to the client.
In short there's no way you can easily and absolutely block blacklisted sites from using your widget.

Is there a way to mitigate downloading of resources (images/css and js files) with Javascript?

I have a html page on my localhost - get_description.html.
The snippet below is part of the code:
<input type="text" id="url"/>
<button id="get_description_button">Get description</button>
<iframe id="description_container" src="#"/>
When the button is clicked the src of the iframe is set to the url entered in the textbox. The pages fetched this way are very big with lots of linked files. What I am interested in the page is a block of text contained in a <div id="description"> element.
Is there a way to mitigate downloading of resources linked in the page that loads into the iframe?
I don't want to use curl because the data is only available to logged in users and the steps to take with curl to get the content is too complicated. The iframe is simple as I use this on a box which sends the right cookies to identify the request as coming from a logged in user, but the problem is that it is very wasteful to get nearly 1 MB of data to keep 1 KB of it and throw out the rest.
Edit
If the proposed method just works in Firefox it is fine, so I added Firefox tag. Also, it is possible that the answer actually is from the realm of Firefox add-on techniques, so I added that tag as well.
The problem is not that I cannot get at what I'm looking for, rather, the problem is the easy iframe method is wasteful.
I know that Firefox does allow loading only the text of a page. If you open a page and press Ctrl+U you are taken to 'view page source' window, There links behave as normal and are clickable, if you click on a link in source view, the source of the new page is loaded into the view source window, without the linked resources being downloaded, exactly what I'm trying to get. But I don't know how to access this behaviour.
Another example is the Adblock add-on. It somehow kills elements before they get loaded. With plain Javascript this is not possible. Because it only is triggered too late to intervene in good time.
The Same Origin Policy forbids any web page to access contents of any other web page in a different domain so basically you cannot do that.
However it seems that with some browsers it is allowed to access web pages content if you are trying to access it from a local web page which seems to be your case.
Safari, IE 6/7/8 are browser that allow a local web page to do so via XMLHttpRequest (source: Google Browser Security Handbook) so you may want to choose to use one of those browsers to do what you need (note that future versions of those browsers may not allow to do so anymore).
A part from this solution I only see two possibities:
If the web pages you need to fetch content from are somehow controlled by you, you can create a simpler interface to let other web pages to get the content you need (for example allowing JSONP requests).
If the web pages you need to fetch content from are not controlled by you the only solution I see is to fetch content server side logging in from the server directly (I know that you don't want to do so, but I don't see any other possibility if the previous I mentioned are not practicable)
Hope it helps.
Actually I've seen Cross Domain jQuery .load request before, here: http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
The author claims that codes like these found on that page
$('#container').load('http://google.com'); // SERIOUSLY!
$.ajax({
url: 'http://news.bbc.co.uk',
type: 'GET',
success: function(res) {
var headline = $(res.responseText).find('a.tsh').text();
alert(headline);
}
});
// Works with $.get too!
would work. (The BBC code might not work because of the recent redesign, but you get the idea)
Apparently it is using YQL wrapped into a jQuery plugin to do the trick. Now I cannot say I fully understand what he is doing there but it appears to work, and fits the bill. Once you load the data I suppose it is a simple matter of filtering out the data that you need.
If you prefer something that works at the browser level, may I suggest Mozilla's Jetpack framework for lightweight extensions. I've not yet read the documentations in its entirety but it should contain the APIs needed for this to work.
There are various ways to go about this in AJAX, I'm going to show the jQuery way for brevity as one option, though you could do this in vanilla JavaScript as well.
Instead of an <iframe> you can just use a container, let's say a <div> like this:
<div id="description_container"></div>
Then to load it:
$(function() {
$("#get_description_button").click(function() {
$("#description_container").load($("input").val() + " #description");
});
});
This uses the .load() method which takes a string in this format: .load("url selector"), then takes that element in the page and places it's content inside the container you're loading, in this case #description_container.
This is just the jQuery route, mainly to illustrate that yes, you can do what you want, but you don't have to do it exactly like this, just showing the concept is getting what you want from an AJAX request, rather than in an <iframe>.
Your description sounds like you are fetching pages from the same domain (you said that you need to be logged in and have session credentials) so have you tried to use async request via XMLHttpRequest? It might complain if the html on a page is particularly messed up but you chould still be able to get raw text via .responseText and extract what you need with a regex.

Categories