Adding Dynamic Code to Javascript (in the simplest way possible) in ASP.NET

In a (Sitecore) project that I work on, we add Google’s Google Analytics async code to the head tag of the page by using a Web Control (.ascx). Recently a requirement has come up to add additional tracking parameters to this javascript for a couple of sites that use this code.

Problem
What is the cleanest way to add arbitrary code to javascript within script tags, given that an asp:Literal or similar tag cannot be added within the script tags?

The default Javascript is as expected:

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXXX-X']);
  _gaq.push(['_setDomainName', 'none']);
  _gaq.push(['_setAllowLinker', true]);
  _gaq.push(['_trackPageview']);
  _gaq.push(['_trackPageLoadTime']); 

(function() {
    var ga = document.createElement('script'); 
    ga.type = 'text/javascript'; ga.async = true;
    
    // lines deleted for clarity
}
</script> 

For certain legacy reasons we need to add a second set of parameters to the call:


<script type="text/javascript">
var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXX-1']);
  _gaq.push(['_setDomainName', 'none']);
  _gaq.push(['_setAllowLinker', true]);
  _gaq.push(['_trackPageview']);
  _gaq.push(['_trackPageLoadTime']); 

  _gaq.push(['XYZ._setAccount', 'UA-XXXXXX-2']);
  _gaq.push(['XYZ._setDomainName', 'none']);
  _gaq.push(['XYZ._setAllowLinker', true]);
  _gaq.push(['XYZ._trackPageview']);
  _gaq.push(['XYZ._trackPageLoadTime']); 


(function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript'; ga.async = true;
    
    // lines deleted for clarity
}
</script>

Ideally, I would like the block of code that defines the base javascript and the addition to resemble the final javascript, so that it is very obvious to any future developer what the intent is, should the code need to change.

Solution
Although asp tags cannot be added within the script tag, What are probably called server-side scripting delimiters can be used.

The simplest solution is to add a protected member to the code-behind of the control and then reference it using the server-side scripting delimiter syntax: .

The .ascx file looks like this:

<script type="text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-XXXXXX-1']);
    _gaq.push(['_setDomainName', 'none']);
    _gaq.push(['_setAllowLinker', true]);
    _gaq.push(['_trackPageview']);
    _gaq.push(['_trackPageLoadTime']);

    <%=LegacyAnalyticsData%>

(function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript'; ga.async = true;
    
    // lines deleted for clarity
}
</script>

The code-behind looks like this:

protected string LegacyAnalyticsData
{
    get
    {
        const string legacyData =
                
        @"_gaq.push(['_setAccount', '{0}']);
        _gaq.push(['{1}._setDomainName', 'none']);
        _gaq.push(['{1}._setAllowLinker', true]);
        _gaq.push(['{1}._trackPageview']);
        _gaq.push(['{1}._trackPageLoadTime']);";

        // item retrieved already
        var legacyCode = item["LegacyGoogleAnalyticsCode"];
        var prefix = item["LegacyGoogleAnalyticsPrefix"];

        if(!string.IsNullOrEmpty(legacyCode)  
            && !string.IsNullOrEmpty(prefix))
        {
            return string.Format(legacyData, legacyCode, prefix);
        }

        return string.Empty;
    }
}

So, if the javascript code needs to change, both the base-line case and the minority case are in one place, and both look like the resulting javascript snippets will look. This means that if the javascript needs to change, the intent of the code should be manifestly evident, and simple.