4

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 value 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:

HTML structure with no Google Analytics code

However, as soon as I add Google Analytics code, the HTML gets screwed:

HTML structure with Google Analytics code

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.

CesarGon
  • 15,099
  • 6
  • 57
  • 85
  • Can we see the relevant sections of the source for your page? Check that your script tags are closed and perhaps try moving them to the end of the page rather than the beginning. – mikey Jun 05 '11 at 15:59
  • @mikey: All the tags are properly closed; I have quadruple (at least) checked. I will post some source tomorrow as soon as I get to my office. What sections of the page source would you like to see? I will also try moving the reference to the Google Analytics script to the end of the page. Thanks. – CesarGon Jun 05 '11 at 17:24
  • Please check that you're closing the tag also. I've never seen such strangeness, I do think it is something small and easy to miss like that though. Beyond that I'd probably start looking at the .js code itself for anything odd. – mikey Jun 05 '11 at 17:52
  • Just to clarify, are you pasting the Google Analytics code right at the end of your page (Just before `

    `)?

    – keyboardP Jun 05 '11 at 17:58
  • @keyboardP: No. I am pasting it right before the closing tag, as Google suggests. – CesarGon Jun 06 '11 at 11:09
  • @CesarGon - I wasn't sure whether you were using the traditional script (where it goes in the body http://code.google.com/apis/analytics/docs/tracking/gaTrackingOverview.html#trackingCodePlacement) or the async one. No matter, at least it's fixed :) – keyboardP Jun 06 '11 at 13:40
  • @keyboardP: Oh I see. Well, thanks for your help though. :-) – CesarGon Jun 06 '11 at 17:19

5 Answers5

3

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.

Community
  • 1
  • 1
CesarGon
  • 15,099
  • 6
  • 57
  • 85
  • you have found answer to your own question... Cheers :D – Nitin Sawant Jun 08 '11 at 07:27
  • @TFD: I am using the new, async code. Please see http://www.google.com/support/googleanalytics/bin/answer.py?answer=174090 where it is clear and in bold face that the code should be inserted "just before the closing tag". The page you quote refers to the old ("traditional") version of the code. – CesarGon Jun 09 '11 at 01:29
  • @CeasarGon - See my answer. [Paul Irish](http://paulirish.com) works for Google in the dev community and said that the only reason Google suggests to place the snippet as high as possible it to track as soon as possible. He said, he disagrees with the notion of tracking a visit that leaves before the page loads, and thus, puts its right before the closing `

    ` tag so that he knows every tracked visit is a real visit.

    – Code Maverick Jun 09 '11 at 21:27
  • @Scott: Thanks for your comment. My OP is not about where to put the script; that topic has somehow arisen as a secondary issue, but I didn't intend to discuss it. My OP is about ill-formatted HTML that was produced, apparently, as a result of the interaction of the Google Analytics code and something else. Fortunately, this has been solved a few days ago already, as you can see in my own answer as well as the OP. Thank you anyway. :-) – CesarGon Jun 09 '11 at 23:27
  • @CesarGon - No, I know. My comment was just in response to your comment where you saying that google's site made it clear that the code should be inserted before the closing `` tag. I just wanted to tell you why they said that. – Code Maverick Jun 10 '11 at 15:28
  • Thanks - this also solved a similar problem using a jquery plugin. – ccook Feb 02 '12 at 13:54
1

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>
casperOne
  • 73,706
  • 19
  • 184
  • 253
Michele
  • 11
  • 2
1

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.

Gijs
  • 5,201
  • 1
  • 27
  • 42
  • Google suggests that you put the script right before the closing tag, rather than inside the body. I am following Google's advice. I have tried moving it to the body too, but things do not improve. – CesarGon Jun 06 '11 at 11:10
  • Actually, Google says both at the end of the `` and at the end of the body are fine, if you read Theofanis' link closely. If you put the tag in the body, I would be extremely surprised if the breakage would be the same, because the `` tag will be the same as it was without any google analytics script. The script will insert a script element next to the first script tag, so you could also try moving all scripts to the body. In any case, we will probably need the generated HTML source (rather than a screenshot) to figure out what is wrong here. – Gijs Jun 06 '11 at 11:36
  • Also, what are the contents of the `_private` google analytics js file? Are you `document.writing` anything from there? Modifying the DOM in some other way? – Gijs Jun 06 '11 at 11:38
  • @Gijs: I cannot find any reference in Google's documentation to putting GA script in the body. The link provided by Theofanis says that *other* scripts may be put in the body, but does not say that GA script should; at least, I cannot see it. Regarding your other question, the `_private/GoogleAnalytics.js` file contains *exactly* the code posted by Theofanis, i.e. the code that otherwise you would paste between the `` tags in your page. – CesarGon Jun 06 '11 at 11:50
  • @CesarGon: glad you solved the problem! As for my reference, the exact quote is: "For the best performance across all browsers we suggest you position other scripts in your site in one of these ways: - before the tracking code snippet in the section of your HTML - after both the tracking code snippet and all page content (e.g. at the bottom of the HTML body)" (my apologies for the poor formatting, I am unable to figure out how to make Markdown behave better in comments...) – Gijs Jun 06 '11 at 11:53
  • @Gijs: Thank you! I saw that section, and I understand it to refer to *other* scripts (i.e. "...you position *other* scripts in your site..."). It is asking you to put other scripts either before the GA scripts, or at the very end, such as at the bottom of the body. It is discussing where to put other scripts rather than the GA script. – CesarGon Jun 06 '11 at 11:55
  • ... and I should learn to read. Sorry! Although I respectfully disagree with Google about it being "customary" to put scripts in the head tag... (And where I work, we have the script tag at the end of `` on all of our web properties (several million visitors a day) and we don't have any issues). – Gijs Jun 06 '11 at 11:56
  • :-D No problem! Thanks for your help, though! – CesarGon Jun 06 '11 at 12:00
1

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

Theofanis Pantelides
  • 4,724
  • 7
  • 29
  • 49
  • What is "incorrect" with what I've stated? I know what the Google Analytics script looks like; thanks. :-) And I am putting it exactly there, right before the closing tag. – CesarGon Jun 06 '11 at 11:11
1

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.

Code Maverick
  • 20,171
  • 12
  • 62
  • 114
  • Thanks for the great link, Scott. And for the interesting point about not tracking partially loaded pages. The issue I described in the OP was solved a couple of days ago, though. – CesarGon Jun 09 '11 at 23:29