Google Website Optimiser Control Javascript - javascript

Could someone explain the javascript that makes up Google's Website Optimiser Control script? Specifically: the first two lines, which seem to be empty functions, and why is the third function wrapped parentheses () ?
As far as I can tell this script is basically writing out a new <script> which presumably loads something for A/B testing.
function utmx_section(){}
function utmx(){}
(function() {
var k='0634742331',d=document,l=d.location,c=d.cookie;
function f(n) {
if(c) {
var i=c.indexOf(n+'=');
if (i>-1) {
var j=c.indexOf(';',i);
return escape(c.substring(i+n.length+1,j<0?c.length:j))
}
}
}
var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;
d.write('<sc'+'ript src="'+'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com'+'/siteopt.js?v=1&utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+'" type="text/javascript" charset="utf-8"></sc'+'ript>')
}
)();
I've attempted to step through with the firebug debugger but it doesn't seem to like it. Any insights much appreciated.
Many thanks

inside anonymous function it shortens names of document and cookies inside it at first, function f(n) gets value of cookie under name n. Then Google reads its cookies and with help of d.write it loads its scripts (as I see they are related to Google Analytic). This way it makes On-Demand JavaScript loading... Actually you load these scripts all the time, Google just needs some additional parameters in url, so this is done this way - save parameters in cookie, which next time are used to get script again.
And finally back to the first two magic lines :) After Google loads its script (after executing d.write), there are some functions which uses utmx and utmx_section, as well as definition of these functions, or better to say overriding. I think they are empty at first just because another function can execute it before its real definition, and having empty functions nothing will happen (and no JS error), otherwise script would not work. E.g. after first iteration there is some data, which is used to make real definition of these functions and everything starts to work :)

The first 2 functions are in fact empty, and are probably overridden later on.
The third function is an anonymous self-executing function. The brackets are a convention to make you aware of the fact that it is self executing.
the "f" function looks up the value given to it in the document's cookies and returns it. Then a new script tag is written to document (and requested from server) with these values as part of its URL.

Related

When in the Chrome Debugger, is there anyway to reference data or functions inside an anonymous function block?

I'm trying to debug something live on a customer website and my code is all inside an anonymous function block. I don't know if there's anyway to reach that code to execute functions or look at variables in there. I can't put a breakpoint either because this code is dynamically generated each time the page is refreshed and the breakpoint doesn't stick.
(function() {
var Date = "14 September 2022 14:44:55"; // different every refresh for example
var Holder = {
var Items = {
item1: "Value1",
item2: "Value2"
};
function getItem(name) {
return Items[name];
};
function setItem(name, value) {
Items[name] = value;
};
setTimeout(DoSomething(), 2000);
})();
That's not the actual code, just a bare minimum example to illustrate the problem.
Is there anyway to get reach getItem() or Items?
Without a breakpoint that code probably runs to completion then POOF it's all gone anyway.
Redefine setTimeout
If it really is the case that the code inside the anonymous function calls other browser methods, you might be able to insert a detour at runtime that you can then put a breakpoint on.
For this to work, you will need to be able to inject new code into the page before the anonymous code, because there's no other way to invoke the IIFE.
Your example code uses setTimeout, so here's what I would try to insert:
let realSetTimeout = window.setTimeout
window.setTimeout = (...args) => {
debugger
return realSetTimeout(...args)
}
Lots of unrelated code might be calling setTimeout, in which case this could break the page or just make debugging really tedious. In that case, you might make it only debug if one of the setTimeout args has a value that's used in your example, e.g.:
// only break for our timeout
if(args[1] === 2000) debugger
Something like that might not trigger for only your code, but it would hugely reduce the number of other codepaths that get interrupted on their journey through the commonly-used browser capability.
Alternatively, use Charles Proxy to rewrite the body of the HTML page before it enters your browser. You could manually insert a debugger call directly into the anonymous function. Charles is not free, but I think they have a demo that might let you do this. If you do this professionally, it's probably a good purchase anyway. Your employer might even pay for the license.
If you can't use Charles (or a similar tool), you could instead set up a local proxy server using Node which does the rewrite for you. Something like that might only take an hour to throw together. But that is a bigger task, and deserves its own question if you need help with that.
No unfortunately.
The variables inside of the anonymous object are created in a scope which is inaccessible from the outside.
One of the main benefits of using a closure!
You’ll have to find a way to insert your own code inside of it by modifying the function that is generating those objects. If you can’t do that, then you’ll have to take the fork in the road and find another way.

QtWebKit bridge: call JavaScript functions

I am writing a hybrid application with HTML interface and Python code.
I can access Python functions via a shared object:
pythonPart.py:
class BO(QObject):
def __init__(self, parent=None):
super(BO, self).__init__(parent)
#Slot(str)
def doStuff(self, txt):
print(txt)
bridgeObj = BO()
# init stuff and frame...
frame.addToJavaScriptWindowObject( 'pyBridge', bridgeObj )
frame.evaluateJavaScript('alert("Alert from Python")')
frame.evaluateJavaScript('testMe()')
frame.evaluateJavaScript('alert("Starting test");testMe();alert("Test over")')
jsPart.js:
function testMe() { alert('js function testMe called'); }
pyBridge.doStuff("bla");
testMe();
Calling Python functions from JS works, as does calling testMe from JS. Calling "standard" JS functions like alert from Python works, too.
The last two Python lines won't:
evaluateJavaScript("testMe()") doesn't do anything at all.
The last line executes the first alert and won't continue after that.
EDIT: I already tried having some time.sleep() between loading and calling the evaluateJavaScript and I'm loading the webpage from the local machine.
The most likely problem is that the JavaScript just isn't loaded yet. Adding time.sleep() calls doesn't help for that, those will also block the Qt event loop from continuing, not just your Python code.
Try waiting for the page to have fully loaded instead, for example (using the loadFinished signal:
def onLoad():
frame.evaluateJavaScript('testMe()')
frame.loadFinished.connect(onLoad)
Aditionally, for getting more debug information in situations like this, you might want to implement QtWebKit.QWebPage.javaScriptConsoleMessage.
There are at least two errors in the example code.
Firstly, when you add the object to the javascript window, you call it "pyBridge", but you then try to reference it in the javascript as "bridgeObj". Obviously, this will throw a ReferenceError which will prevent any further execution of the script.
Secondly, the doStuff method is missing a self argument, which will cause a TypeError to be raised by PySide.
Dealing with those two issues should be enough to fix your example code, so long as you make sure that the bridge object is added to the javacsript window before the html is loaded. This step is required if you want to reference the bridge object in top-level javascript code. However, if the bridge object is only ever referenced in function-level code, it can be safely added to the javascript window after the html has loaded.

Function Undefined: Must a javascript function be defined within the same file?

I've got a file notifications.js containing one event bound to an element, and a function updateNotification(). This function uses jQuery to update certain elements on the page when a JSON object is passed as a parameter.
The problem:
I'm attempting to call this function within the page (via <script> tags), however rather than calling it, it breaks the page. I did some digging around within the Chrome Developer Console (not sure of the name), and an error is flagged:
/pleaseshare/views/install/:50 Uncaught ReferenceError:updateNotification is not defined
However, when I pan within the console, I can clearly see the file notifications.js listed under scripts, and the function is defined there. If I define the function within the current scope (e.g. the line above the call), it works fine.
What I've tried
The function contains some javascript that requires jQuery, so I've attempted both with and without encasing it in $(document).ready( function() {});, with neither seeming to have any affect.
I'm pretty stumped.
For good measure, here's a link to show the structure of my javascript and html: http://snippi.com/s/znk6xe9
Any help in figuring out why this is happening, or explanations of why javascript functions cannot be called cross-file (although I'd hope this isn't the case), would be greatly appreciated ;)!!
A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.
A function cannot be called unless it is in the same or greater scope then the one trying to call it.
You code looks like the structure should work, but is clearly a reduced test case that has been reduced to the point where it won't.
Got it working. The issue was definitely multi-faceted, but I figured it out.
First off the use of RequireJS had an impact on updateNotification(), in that it couldn't be called cross-file, and was therefore considered undefined. I assume this because of how RequireJS loads files, and I'll look into the documentation later (and post an edit if I find anything relevant).
Secondly, updateNotification() would again be considered undefined when encased within jQuery's DOM ready loader $(document).ready(function(){}). However updateNotification() contains executions which require jQuery, so I had to encase the contents of the function in $(document).ready(function(){}).
This is an issue very unique to RequireJS/jQuery, hence why in most use cases this wouldn't occur.
Side note: The tags are edited to reflect this.
you need to import your script into your page:
<script type="text/javascript" language="javascript" src="path/to/notifications.js"></script>
This needs to be added above the <script> tag that calls updateNotification()
Functions do not need to be declared in the same file. In fact, avoiding having every declaration dumped into the global namespace is usually a concern in JavaScript.
In the sample code in the link you provided, updateNotification is declared as a global, so there should not be a scoping problem.
However, in the same sample, you don't show notifications.js being included. You need to import it using a <script></script> element and that element must come before the script element that includes the call to updateNotification. You also must include jQuery before notifications.js, since it uses jQuery. So you need something like:
<body>
// One or two elements
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="notifications.js"></script>
<script type="text/javascript">
$(document).ready( function() {
var json = {status : 'ok', message: 'Hello'};
updateNotification(json);
});
</script>
// All other elements
</body>

Debugging Javascript functions in Firebug

I am trying to debug legacy scripts with Firebug. As per my knowledge (Which I got yesterday)
we use Step over (F10) to debug line by line and Step into (F11) to dig into JS function.
But when I use Step into on any JS function call, it takes control to next line. I want to see what is hidden inside the function. How can we do it ?
I kept break-point inside the function and then tried Step into then it takes control inside the function body. But it is tedious to find each function method and set break-point.
Is there any other way to do it ? or which is the right way ?
For example :
i2b2.ONT.ctrlr.FindBy = {
clickSearchName: function() {
// do some stuff
i2b2.ONT.ctrlr.FindBy.doNameSearch(search_info); // I tried Step into here
// some more stuff
}
doNameSearch: function(inSearchData) {
// If I set break-point here then only I can debug it
// or it directly takes control to `// some more stuff` in `clickSearchName:function`
}
}
PS: It also more external JS function calls.
Thanks,
Ajinkya.
"Step into" will step into the function if there is JS source for the function. If not (like for document.getElementById("foo"), it will step over it since it doesn't have anything that it understand to step into.
If you can point us to a working example where you are having the problem (either a jsFiddle reduction of the problem or a working web page) with instruction on where the relevant code is, we can probably help more.
Judging by your code example, I'm wondering what you're trying to step into. The line of code that starts with clickSearchName defines a function. It doesn't execute it. So, it won't go into that function until some later code actually calls clickSearchName. So, perhaps you're breaking on the definition of the function and trying to step into the function when it isn't being executed. That's just a guess though since we don't have a working example to try ourselves.
Add the line debugger; to your code at the place where you want to break into the debugger, it's a JavaScript keyword, which should do what you want. Just remember to take it out when you're done debugging your code.

Why is my JavaScript function sometimes "not defined"?

I call my JavaScript function. Why do I sometimes get the error 'myFunction is not defined' when it is defined?
For example. I'll occasionally get 'copyArray is not defined' even in this example:
function copyArray( pa ) {
var la = [];
for (var i=0; i < pa.length; i++)
la.push( pa[i] );
return la;
}
Function.prototype.bind = function( po ) {
var __method = this;
var __args = [];
// Sometimes errors -- in practice I inline the function as a workaround.
__args = copyArray( arguments );
return function() {
/* bind logic omitted for brevity */
}
}
As you can see, copyArray is defined right there, so this can't be about the order in which script files load.
I've been getting this in situations that are harder to work around, where the calling function is located in another file that should be loaded after the called function. But this was the simplest case I could present, and appears to be the same problem.
It doesn't happen 100% of the time, so I do suspect some kind of load-timing-related problem. But I have no idea what.
#Hojou: That's part of the problem. The function in which I'm now getting this error is itself my addLoadEvent, which is basically a standard version of the common library function.
#James: I understand that, and there is no syntax error in the function. When that is the case, the syntax error is reported as well. In this case, I am getting only the 'not defined' error.
#David: The script in this case resides in an external file that is referenced using the normal <script src="file.js"></script> method in the page's head section.
#Douglas: Interesting idea, but if this were the case, how could we ever call a user-defined function with confidence? In any event, I tried this and it didn't work.
#sk: This technique has been tested across browsers and is basically copied from the Prototype library.
I had this function not being recognized as defined in latest Firefox for Linux, though Chromium was dealing fine with it.
What happened in my case was that I had a former SCRIPT block, before the block that defined the function with problem, stated in the following way:
<SCRIPT src="mycode.js"/>
(That is, without the closing tag.)
I had to redeclare this block in the following way.
<SCRIPT src="mycode.js"></SCRIPT>
And then what followed worked fine... weird huh?
It shouldn't be possible for this to happen if you're just including the scripts on the page.
The "copyArray" function should always be available when the JavaScript code starts executing no matter if it is declared before or after it -- unless you're loading the JavaScript files in dynamically with a dependency library. There are all sorts of problems with timing if that's the case.
My guess is, somehow the document is not fully loaded by the time the method is called. Have your code executing after the document is ready event.
Verify your code with JSLint. It will usually find a ton of small errors, so the warning "JSLint may hurt your feelings" is pretty spot on. =)
A syntax error in the function -- or in the code above it -- may cause it to be undefined.
This doesn't solve your original problem, but you could always replace the call to copyArray() with:
__args = Array.prototype.slice.call(arguments);
More information available from Google.
I've tested the above in the following browsers: IE6, 7 & 8B2, Firefox 2.0.0.17 & 3.0.3, Opera 9.52, Safari for Windows 3.1.2 and Google Chrome (whatever the latest version was at the time of this post) and it works across all browsers.
If you're changing the prototype of the built-in 'function' object it's possible you're running into a browser bug or race condition by modifying a fundamental built-in object.
Test it in multiple browsers to find out.
This has probably been corrected, but... apparently firefox has a caching problem which is the cause of javascript functions not being recognized.. I really don't know the specifics, but if you clear your cache that will fix the problem (until your cache is full again... not a good solution).. I've been looking around to see if firefox has a real solution to this, but so far nothing... oh not all versions, I think it may be only in some 3.6.x versions, not sure...
Solved by removing a "async" load:
<script type="text/javascript" src="{% static 'js/my_js_file.js' %}" async></script>
changed for:
<script type="text/javascript" src="{% static 'js/my_js_file.js' %}"></script>
Use an anonymous function to protect your local symbol table. Something like:
(function() {
function copyArray(pa) {
// Details
}
Function.prototype.bind = function ( po ) {
__args = copyArray( arguments );
}
})();
This will create a closure that includes your function in the local symbol table, and you won't have to depend on it being available in the global namespace when you call the function.
This can happen when using framesets. In one frame, my variables and methods were defined. In another, they were not. It was especially confusing when using the debugger and seeing my variable defined, then undefined at a breakpoint inside a frame.
I'm afraid, when you add a new method to a Function class (by prtotyping), you are actually adding it to all declared functions, AS WELL AS to your copyArray(). In result your copyArray() function gets recursivelly self-referenced. I.e. there should exist copyArray().bind() method, which is calling itself.
In this case some browsers might prevent you from creating such reference loops and fire "function not defined" error.
Inline code would be better solution in such case.
I think your javascript code should be placed between tag,there is need of document load

Categories

Resources