编辑:为了澄清,我的主要问题归结为:如果您向某个服务器(在本例中为Google)发出AJAX请求,但客户端会在服务器之前离开该页面完成请求,是否有可能(或可能)服务器也会中止请求,或服务器是否会尝试完成请求(尽管没有人再响应)?
如果您愿意,请随意阅读所有细节的其余部分。
我正在一个旨在立即重定向的网页上使用Google Analytics。由于Google javascript文件ga.js
是异步加载的,因此我需要确保跟踪javascript动态添加的所有脚本标记,并且只有在这些脚本完成后才会发生页面重定向。我已经处理了那部分。
文件ga.js
似乎向带有参数的__utm.gif
文件发出请求,这是执行实际跟踪的内容。该请求显然不是来自我可以控制的文件,所以这是我的问题:
首先,请求是异步的(我怀疑它是)?其次,在重定向页面之前,如何确保该请求有时间完成(我希望在“足够的时间”过后不再简单地重定向)?如果在请求完成之前重定向原始页面,请求是否仍然完成(毕竟,我不需要Google提供任何数据)?
编辑:这是我的代码:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Redirecting...</title>
<script type="text/javascript">
/* <![CDATA[ */
// Holds a value for each script. When all the values contained in this array are true, all loading has completed.
var scripts = [];
function scriptDetectLoaded(script)
{
scripts.push({ loaded: false, element: script });
var index = scripts.length - 1;
// Will set this script as loaded
var callback = function ()
{
//console.log("Script with index " + index + " finished loading");
scripts[index].loaded = true;
};
// For most browsers
script.onload = callback;
// For IE
script.onreadystatechange = function ()
{
if (this.readyState == "complete")
callback();
};
return index;
}
/* ]]> */
</script>
<!-- Google analytics code -->
<script type="text/javascript">
/* <![CDATA[ */
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-MY_ID-1']);
_gaq.push(['_trackPageview']);
(function ()
{
//debugger;
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
scriptDetectLoaded(ga); var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
/* ]]> */
</script>
</head>
<body>
<noscript>
<p>Please enable JavaScript and refresh this page. Our site won't work correctly without it.</p>
<p><a href="http://www.google.com/search?q=how+to+enable+javascript" target="_blank">How do I enable JavaScript?</a></p>
</noscript>
<!-- Google Code for New Account Conversion Page -->
<script type="text/javascript">
/* <![CDATA[ */
//debugger;
var google_conversion_id = SOME_ID;
var google_conversion_language = "en";
var google_conversion_format = "2";
var google_conversion_color = "ffffff";
var google_conversion_label = "SOME_LABEL";
var google_conversion_value = 0;
(function () {
var gad = document.createElement('script'); gad.type = 'text/javascript'; gad.async = true;
gad.src = document.location.protocol + "//www.googleadservices.com/pagead/conversion.js";
scriptDetectLoaded(gad); var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gad, s);
})();
/* ]]> */
</script>
<noscript>
<div style="display:inline;">
<img height="1" width="1" style="border-style:none;" alt="" src="http://www.googleadservices.com/pagead/conversion/1056222251/?label=keCSCNO9qAIQq9jS9wM&guid=ON&script=0"/>
</div>
</noscript>
<!-- Redirect Page -->
<script type="text/javascript">
/* <![CDATA[ */
//debugger;
var url = '/console';
var interval = 100 /*milliseconds*/;
var timeout = 5000 /*milliseconds*/;
var count = 0;
// Set a repeating function that checks to ensure all the scripts have loaded.
// Once all the scripts have loaded, redirect the page.
var id = setInterval(function ()
{
count += interval;
// Check for timeout
if (count > timeout)
{
//console.log("Timed out.");
redirect();
}
// Check to make sure all scripts have loaded
for (var i = 0, len = scripts.length; i < len; i++)
{
if (!scripts[i].loaded)
return;
}
// If we make it here, redirect
redirect();
}, interval);
function redirect()
{
location.replace(url);
// Run this in case the page doesn't redirect properly.
clearInterval(id);
var a = document.createElement("a");
a.href = url;
a.innerHTML = "Please click here to proceed";
var p = document.getElementById("message");
p.innerHTML = "";
p.appendChild(a);
}
/* ]]> */
</script>
<p id="message">Please wait as we redirect the page.</p>
</body>
</html>
答案 0 :(得分:1)
如果您在请求完成之前重定向,它将在客户端被取消。意思是,服务器可能已经获得了帖子并对其采取了行动,但是你不会得到结果。如果这些项是动态添加的,则不能使用任何onload类型的函数。我会想象你添加的谷歌文件会有一些你可以用来重定向你的回调。
编辑:如果你想以一种你将完全知道何时完成加载的方式加载脚本,这样你就可以重定向到另一个页面,我将使用jquery的$ .getScript函数。它允许在文件加载后进行回调,然后您可以立即重定向api.jquery.com/jQuery.getScript
答案 1 :(得分:0)
对于依赖于__utm.gif的跟踪,不需要完成请求以使度量标准生效。一旦浏览器发送请求(包含所有参数),GA就能满足它的需求。所以你只需要确保图像请求触发。
如果这是一个没有真实内容的插页式页面,您可以执行诸如检查文档图像集合的长度等操作;当长度> 0,那么你知道GA创建了IMG并设置了它的src(从而触发了请求)。不确定该集合的细节,但我知道过去存在的东西;也许它仍然存在。在这种情况下,执行测试并启动重定向的简单setInterval就足够了。
编辑:由于GA的东西会在文档中添加脚本,因此您可以检查DOM结构以查看是否存在具有正确src值的脚本。这可能会让你更接近于从正确的事件中链接重定向。
答案 2 :(得分:0)
对于当前的ga.js状态,您可以使用以下代码检查跟踪完成情况:
(function (global) {
var listeners = []
, ImageReworked
, ImageNative = Image
;
function stringMatch(haystack, needle) {
if (typeof needle.valueOf() === 'string' && haystack.indexOf(needle) !== -1) {
return true;
} else if (needle instanceof RegExp && haystack.match(needle)) {
return true;
}
}
global.addImageListener = function (url, handler) {
if (!listeners.length) {
Image = ImageReworked;
}
listeners.push([url, handler]);
};
global.removeImageListener = function (url, handler) {
var newListeners = [];
listeners.forEach(function (el) {
if (url.constructor !== el[0].constructor //this will not work for object in different windows
|| el[0].toString() !== url.toString()
|| (handler && handler !== el[1])) {
newListeners.push(el);
}
});
listeners = newListeners;
if (!listeners.length) {
Image = ImageNative;
}
};
ImageReworked = function(w, h) {
var i = new ImageNative(w, h)
;
function handler() {
listeners.forEach(function (el) {
var url = el[0]
, handler = el[1]
;
if (stringMatch(i.src, url)) {
handler(i.src);
}
});
}
if (i.addEventListener) {
i.addEventListener('load', handler, false);
} else if (i.attachEvent) {
i.attachEvent('onload', handler);
}
return i;
};
})(window);
用法示例:
addImageListener(/__utm/, function (src) {
var parameters = {};
window.removeImageListener(new RegExp('__utm'));//see, regexp can be created by new RegExp!
(foundParameters = src.match(/(\?|&)(.*?\=[^?&]*)/g)) && foundParameters.forEach(function (parameter) {
var pair = parameter.replace(/^(\?|&)/, '').split('=');
parameters[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
});
console.log(parameters);
});
_gaq.push(['_setAccount', gaid], ['_trackPageview']);
但是你应该记住,如果GA更改了他们的跟踪逻辑,那么这段代码就会被破坏。
你还应该添加超时(如果加载事件永远不会发生的话)。
并且不要使用i.onload,因为GA脚本会覆盖此属性。