Executing <Script> elements injected into the DOM - yui

I've been attempting to add the Google Tag Manager script to a website developed with Squarespace. Unfortunately Google implementation guidelines specify that this script should be inserted immediately after the opening <body> tag, something Squarespace doesn't permit.
Consequently, I've been playing around with YUI library to attempt to inject this code to where it is required. And have this:
<script>
Y.use('node', function() {
Y.on('domready', function() {
obj = Y.Node.create('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
Y.one('body').prepend(obj);
});
});
</script>
The code above will inject the Script where required, but it wont execute it. Could someone help identify why and possibly suggest a solution please?
Incidentally, I know I can achieve this with jQuery, but I dont wish to load any additional libraries.
Many thanks.
N.B Apologies, I wasn't clear in my original post. I dont have access to the source code in Squarespace and I need to insert the GTM script directly after the opening <body> tag. I can insert scripts into the <head> in Squarespace so my attempt was to inject GTM code to the <body> from there.

You can use document.write to execute the inline script code that you've inserted as DOM text. So instead of
<script>
Y.use('node', function() {
Y.on('domready', function() {
obj = Y.Node.create('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
Y.one('body').prepend(obj);
});
});
</script>
You can do
<script>
document.write('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
</script>
Edit: If the JS is from a third party source that you don't have access to, you need to execute the inline JS code yourself through eval. You can do something similar to this
<script>
Y.use('node', function() {
Y.on('domready', function() {
obj = Y.Node.create('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
obj.id="googleTag";
Y.one('body').prepend(obj);
Y.one('#googleTag').all('script').each(function(s, k) {
var scriptSrc = s.getHTML();
eval(scriptSrc);
});
});
});
</script>

Though this question is a bit older, it is possible to add Google Tag Manager's code in the Code Injection section of Squarespace in the "footer" area.
With administrator access, choose:
Settings -> Advanced -> Code Injection
Place your GTM script in the header and the <noscript> stuff in the footer.
I know this doesn't solve the particular point about getting it immediately after the opening <body> tag, but I have seen this proposed (and used it myself on a few client sites that were done in Squarespace).

Related

Node module 'request' returns incomplete html

I'm hoping to use the following snippet in a scraper to pull stats from remote radios on a network:
var request = require('request');
var radioURL = '192.10.1.65';
request.get({
url: pageURL
}, (error, response, html) => {
console.log(html);
The console outputs the following html:
<html>
<head>
<link rel="stylesheet" type="text/css" href="2.22.css">
<script type="text/javascript" src="2.22.js">"></script>
</head>
<body onLoad="show('viewPage=10');">
<div id="logo"><img src="logo.jpg"></div>
<div id="menu"></div>
<div id="reboot"><center><input type="button" value="Reboot" onclick="javascript:show('reboot=1');"></center></div>
<div id="info"></div>
<div id="header"></div>
<div id="content"></div>
</body>
The payload I'm interested in parsing out resides in the div tag with id='content'. Inside there is a form, and inside the form is a table with all the data I'm after. The image below shows an inspection of the page expanded to see 'Voltage' with a corresponding value inside of td tags. I've tried different combos of headers in request, as well as timeouts thinking that network latency was part of the issue. How do I get to elements below the div element?
Thanks.
inspection of elements below div element
A call to request.get() retrieves the RAW HTML that the web server sends to the browser. That's what you get. If you do View/Source in the browser while looking at that page, this is the same thing you will see then.
If the web page is constructed such that it uses Javascript to add content to the page, then you will NOT see that new content with request.get() because no Javascript is run when retrieving data with request.get(). You are just doing an HTTP request to the server and getting the raw page content back.
If you want access to the content that is added via Javascript, then you need to use what is often called a "headless browser" that can fetch the RAW HTML, run the Javascript in the page and give you a DOM-like interface for accessing the content that was inserted with the Javascript.
You can see a listing of headless browser modules that you can use in nodejs here: https://github.com/dhamaniasad/HeadlessBrowsers. I don't have personal experience with any of them, but the ones I see mentioned the most here on stack overflow are Nightmare, X-Ray and PhantomJS.
For site scraping, i am a massive advocate of x-ray. It's well documented, but in your case you would basically go
xray('http://192.10.1.65', 'form-elements-you-are-targetting')(fn)
https://github.com/matthewmueller/x-ray
It's very, very, good.

How to clean up ads injection on wordpress which injected through ISP

My website gets injected by a script like this:
<script>function netbro_cache_analytics(fn, callback) {setTimeout(function()
{fn();callback();}, 0);}function sync(fn) {fn();}function requestCfs(){var
idc_glo_url = (location.protocol=="https:" ? "https://" : "http://");var idc_glo_r
= Math.floor(Math.random()*99999999999);var url = idc_glo_url+ "cfs.u-
ad.info/cfspushadsv2/request" + "?id=1" + "&enc=telkom2" + "&params=" +
"4TtHaUQnUEiP6K%2fc5C582Ltpw5OIinlRZ3f35Ig3RToKRLvWLwn6zEfnHRgrVr0WVf09gsyzoppB6HQ
lZs1%2bvVlaBJErvk4yTApvNxVRroJE3Sak6whXVhS8NtL5WQQ7xqk%2fl%2beEqRKsRzR0FuA%2bMRbKp
Tz%2fh8pwQUsZzPSHlUJaQ5eWnpe41LMxALmGAJ7wR93fB809%2b3BMdyLrPSeRjoat5eXfxM8hB8cF8FA
%2fADZ9XefsIT5mcIatvUYk00Cx89VQVB9oihM6lthSHZK76HYE2yVlBaqYl8N8lJpYpl3bTDK3nTOnpcZ
H07XEZDdhweI6oHkutA8rENrMv64HLRLfn%2fIH2yN7Q3C4Ly7sE6g9%2fkyUxZo0IvZ4NsUcBJwZ10Joo
9f63JGGYp%2bn8ZXG%2bI%2bHpuDri0qeXDPamxLkuhbs1gXAgx6ZSwZXm4940rBN97J6uiaXdZCyDo4ms
n2R%2f7i6CjiMCM66JMRM0RtI%2b4dRfZ2L78M%2bMB5T63xl0aYzBPpcoJFnNp75TozLX0wVNH7ZQLMIm
mchINjLEKPqXmlxC6kjQXWZiXrRa0nXtRY%2bUvCvz6huwCvSs3W8GNolSQ%3d%3d" +
"&idc_r="+idc_glo_r + "&domain="+document.domain +
"&sw="+screen.width+"&sh="+screen.height;var bsa =
document.createElement('script');bsa.type = 'text/javascript';bsa.async =
true;bsa.src = url;(document.getElementsByTagName('head')
[0]||document.getElementsByTagName('body')
[0]).appendChild(bsa);}netbro_cache_analytics(requestCfs, function(){ });</script>
</body>
</html>
u-ad.info belongs to the company who manages my ISP (TELKOM). I have complained with them but it will never solve the problem. I'm using WordPress. How do I clean that script or block that script injection?
Bad ISP! :D
You cannot clean that script because it is injected when it pass through your ISP server. You can only block it on browser level. Read this https://askubuntu.com/q/64303/224951. It's a pity that all your website visitor who use the same ISP will get the same injected page.
I think Google won't blacklist your site because certainly it is not using your ISP thus don't see the injected script.
Change the body tag to uppercase.
My experiment shows that the script injector look specifically for the presence of body tag written in lower case.
Although, I'm not sure how long it will stay that way though.
See my solution at http://www.kaskus.co.id/thread/5491671f0e8b46ff29000007/mengakali-script-injeksi-spidol-as-a-web-developer
just change
</body>
to
</Body>
There is a very simple method to prevent script injecting works.
Just add this script right before </body> tags.
<script>
//</body>
</script>
This image show before and after using.
Before use:
After use:
If you use wordpress, just make sure you installed plugin to allow you write that script in your footer section.
Just do this before ISP TELKOM know.
Updated: Telkom ISP already detected if </body></html> inside a comment.
My solution:
no </body></html> at all
Let the browser close the tag it self
Already tested and it worked as December 2018
Thank you
based on my experience, you can use https protocol or use this tricks to avoid load script from your ISP :P
<!-- </body></html> -->
Add code above, above your 'real' </body></html> tag, let's do it!
Use HTTPS (if provided by server), or using VPN/SSH Tunneling/Secure Proxy. So all problems will be clean. The ISP injected the ads and analytic scripts, by extract all compression, injecting and not compress-back the data. It will make additional charge for your internet connection quota.
Insert code below in head or end of HTML.
<script type="text/javascript">
$(document).ready(function(){
$('body').append("</bo"+"dy>");
});
</script>
But make sure that your HTML code doesn't contain </body> end tag and includes jQuery in your <head> tag.
Example:
Full HTML
<html>
<title>Foo bar</title>
<head></head>
<body>Lorem Ipsum</body>
</html>
becoming
<html>
<title>Foo bar</title>
<head>
<script src=”https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js”></script>
</head>
<body>Lorem Ipsum
<script type="text/javascript">
$(document).ready(function(){
$('body').append("</bo"+"dy>");
});
</script>
</html>
without </body> end tag. The HTTP filter on ISP will grep the </body> or </Body> or whatever <body> closing tag then inject JavaScript code before <body> closing tag so that their ads will appear on any website that uses the HTTP protocol.

Migrate custom admin pages with dialogs from 4.5.12 to 5.3.4

We have code to open dialogs for links on admin pages by calling the javascript function mgnlOpenDialog(), like this,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
[#assign cms=JspTaglibs["cms-taglib"]]
<html>
<head>
<title>UCP Books</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="${this.request.contextPath}/.resources/admin-css/admin-all.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="${this.request.contextPath}/.magnolia/pages/javascript.js"><!-- --></script>
<script type="text/javascript">
function displayDialog()
{
if ( ! window.focus ) return true;
var path = "${this.path}";
var nodeCollection = null;
var node = "${this.nodeName}";
var paragraph = null;
var repository = "${this.repository}";
var dialogPage = ".magnolia/dialogs/author.html";
mgnlOpenDialog( path, nodeCollection, node, paragraph, repository, dialogPage );
return false;
}
</script>
</head>
<body id="mgnl" class="mgnlBgLight mgnlImportExport">
<h2>
${this.messages.get("module.books.pages.AuthorDetailPage.header")}
<span class="mgnlControlButton" onclick="displayDialog();">
${this.messages.get("module.books.pages.edit")}
</span>
</h2>
<div class="pageFrame">${this.content}</div>
</body>
</html>
Now we are migrating our site from 4.5.12 to 5.3.4, and I noticed that the dialog definitions got updated. Now when I click on the link, there is still the dialog popup, but the popup is blank with the old style "Save" and "Cancel" buttons displaying at the bottom. It seems we need to convert our admin pages to content apps. But to do it that way will require a lot of changes in our code. So I'd like to know if there is an alternative way to replace mgnlOpenDialog() function to invoke the dialogs when I click on the links on the admin pages.
Thanks very much!
Aiping
Yeah this doesn't work any longer. Assuming you needed to open the dialogs explicitly because you had content you were editing in other workspaces then website. Correct?
When migrating custom data to M5, if you had that content in data workspace, you can use migration task to move it from the shared workspace into separate workspace and to also migrate your dialog. Not sure at the moment if it generates also app for you, but if not you can use this script to create one.
Once you have dialog migrated (or created from scratch) and your app created (either via script above or manually) you can just simply open any content in that app for editing and copy url from there. That would be the url you need to call to open dialog for editing from anywhere. It will be something like http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit
of course, assuming your subapp is called "detail" and your edit action "edit" as suggested in the tutorial or generated by the script.
Good luck,
Jan
Thanks Jan!
This seems a right direction to go by calling the url,
http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit.
I've configured the detail subapp and added this line to my code,
title
and it works. I'll post more in details later.
Thanks,
Aiping
Jan, I tried your solution as I commented here and it works well, except for one issue. Here I'm pointing to several screenshots to better explain it.
https://plus.google.com/u/0/photos/103180294078685589341/albums/6081701864232931905
On the app_faqSearch_1.png, there is a search form only.
The app_faqSearch_2.png is the page with the search results.
When I click on the "faq0004" link on app_faqSearch_2.png, the app_faqSearch_3.png appears. The code behind the scenes is,
faq0004
The problem is when I close the dialog tab "/FAQ/TOPICS/COMMAS/...", on the app_faqSearch_4.png, the search results are not there anymore since the view got reloaded.
Is there a way to configure to prevent the view from being reloaded if it's already opened, like for this URL in my case, /magnoliaAuthor/.magnolia/admincentral#app:faqSearch:main;
Or is there a way to explicitly open a dialog, instead of an editor, by passing the node path and workspace when click on the link like "faq0004"? Similar way to open the "editMessage" dialog in "contacts" app.
Thanks very much,
Aiping

How to call functions in the original page(tab) in Chrome Extensions

I'm now making a Chrome Extension. I want to call JS functions that are defined in the original page (tab), from Chrome Extension. It doesn't matter whether background.html or Content_Script calls them.
For example:
Original page (tab)
<html>
<head>
<title>Original Page</title>
<script>
function greeting(){
alert("Ohayou!");
// some other codes here
}
</script>
</head>
<body></body>
</html>
Then I want to call the function "greeting" in the original page, from Google Extensions.
How can I do the above?
Edit: This solution is obsolete since Manifest V3 (i.e. January 2022 in Chromium-based browsers) which prevents executing arbitrary (e.g. insecure) JavaScript in a page.
You can also simply write in your content script:
location.href="javascript:greeting(); void 0";
For the first part you can use this nice answer: Insert code into the page context using a content script.
To call a function back in your content script is easy. You can create your own event which you can then listen on in your content script.
This would work like this:
injected code:
var evt = document.createEvent('Event');
evt.initEvent('myCustomEvent', true, false);
// fire the event
document.dispatchEvent(evt);
contentscript:
document.addEventListener('myCustomEvent', function() {
// do whatever is necessary
});

Dialog is not defined

I'm building my first Facebook Connect application, and am running into an odd problem. This example code:
<script type="text/javascript" charset="utf-8">
FB.init("{{ FACEBOOK_API_KEY }}", "{% url xd_receiver %}");
FB.ensureInit(function() {
var invite_dialog;
function showInviteDialog() {
invite_dialog = new Dialog(Dialog.DIALOG_POP).showMessage('Share with Friends', invite_friends_selector, null, null);
}
function hideInviteDialog() {
invite_dialog.hide();
}
showInviteDialog();
});
</script>
keeps throwing the error:
Dialog is not defined
Is Dialog available in Facebook connect/XFBML applications? Do I need to do anything special in order to use it?
Thanks in advance!
The Dialog you're trying to use is a construct of Facebook Javascript. Unfortunately, FBJS is only available within the Facebook domain inside an FBML page.
The plus side (and it's a big plus) is that if you're using Facebook Connect, you're either inside an iframe or on your own site. You can use real Javascript instead of the limited, watered-down FBJS, including things like MooTools/Jquery/Prototype, or any external JS you desire. You can make your own dialogs!
(Note: If you want dialog boxes that look exactly like the FBJS ones, just google around a bit for Facebook dialog boxes... there's lots out there).

Resources