Postback fails on ASP.NET page when using Google Analytics
I am using ASP.NET to create a small web app. One of my pages includes some LinkButton controls, which used to work fine until I added a reference to Google Analytics code to it. Now, when I click on a link button, I get the error message:
Microsoft JScript runtime error: The v开发者_运维百科alue of the property '__doPostBack' is null or undefined, not a Function or object
The other links and controls on the page work fine. If I remove the reference to the Google Analytics script from the page, everything works fine as well. It seems that the problem arises from the interaction between the Google Analytics script and the LinkButton controls trying to postback the page.
UPDATE. I have further observed the following. When no Google Analytics script reference is present, the HTML that ASP.NET generates looks fine:
However, as soon as I add Google Analytics code, the HTML gets screwed:
Check out that form tag! I imagine now that the postback error arises from the fact that the linkbutton controls get placed outside the ASP.NET form. But why? END UPDATE.
Any ideas on how to solve this? Thanks.
FURTHER UPDATE. After much experimenting, I have been able to solve this by myself. I have added an answer below showing my conclusions. Thanks to all who have posted answers here. END UPDATE.
After lots of tweaking, tech support and experimenting, I have fixed the problem. My code looked like this:
<head runat="server">
<title><asp:ContentPlaceHolder ID="cphPageTitle" runat="server"></asp:ContentPlaceHolder></title>
<link href="_private/Normal.css" rel="stylesheet" type="text/css" />
<script src="_private/GoogleAnalytics.js" type="text/javascript" />
</head>
This caused the problem that I describe in my OP. Everything is fixed when I switch to the following:
<head runat="server">
<title><asp:ContentPlaceHolder ID="cphPageTitle" runat="server"></asp:ContentPlaceHolder></title>
<link href="_private/Normal.css" rel="stylesheet" type="text/css" />
<script src="_private/GoogleAnalytics.js" type="text/javascript"></script>
</head>
Notice that the script
is now closed by a full closing tag rather than a self-closing tag. I assumed that script
could be self-closing with no side effects, but apparently things behave differently when you close it differently. This sheds some light on why.
As keyboardP already suggested, you should put the google analytics script in the <body>
element, preferably at the end (so just before the closing </body>
tag), so it won't block the loading of the page. See http://developer.yahoo.com/performance/rules.html#js_bottom for a rationale.
Additionally, it's quite possible that the Google Analytics script adds elements (like that <input>
) which are invalid inside the <head>
element, which would explain why the current setup breaks your page so spectacularly.
That's the incorrect way of adding the Google Analytics code. It should look something like this:
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
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';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
...and it should be pasted right before </head>
tag, according to Google:
http://www.google.com/support/analytics/bin/answer.py?hl=en_US&answer=174090&utm_id=ad
I use Mathias Bynens' method:
<script>
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
(function(d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.async = g.src = '//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
}(document, 'script'));
</script>
Furthermore, the only reason Google suggests that you place it as high up on the document as possible, is so that you can track a visit that might close out of your page before it fully loads. I don't know who would honestly want to track visitors that don't wait for the page to fully load. That, to me, is not a real visit and would throw off numbers. I place it just before the closing </body>
tag, so that I know all my tracked visitors fully loaded the page.
Just
<script type="text/javascript">
if (!<%=Page.IsPostBack.ToString().Tolower()%>)
{
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-xxxxxxxx-xx']);
_gaq.push(['_trackPageview']);
(function() {
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';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
}
</script>
精彩评论