blob: 0a6aba8a206d7c0ed761f6142198f3b4fc4f7c39 [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Make Google Analytics Asynchronous</title>
<link rel="stylesheet" href="doc.css">
</head>
<body>
<!--#include virtual="_header.html" -->
<div id=content>
<h1>Make Google Analytics Asynchronous</h1>
<h2>Configuration</h2>
<p>
The 'Make Google Analytics Asynchronous' filter is enabled by specifying:
</p>
<dl>
<dt>Apache:<dd><pre class="prettyprint"
>ModPagespeedEnableFilters make_google_analytics_async</pre>
<dt>Nginx:<dd><pre class="prettyprint"
>pagespeed EnableFilters make_google_analytics_async;</pre>
</dl>
in the configuration file.
</p>
<h2>Description</h2>
<p>
The filter rewrites pages that load the
<a href="http://www.google.com/analytics/">Google Analytics</a>
tracking code synchronously to load it asynchronously instead.
Loading Google Analytics asynchronously has the advantage that it
will not block resources that load later in the page.
</p>
<p>
Currently, the filter only changes the loading mechanism. To get the
full benefit of the asynchronous load, you should move the loading of
the tracking code to the bottom of the <code>&lt;head&gt;</code> of
the page. That allows beacons to be sent earlier during the page load --
and avoids missing them if a user navigates away from a page quickly.
For more information on how to manually upgrade, see
<a href="/analytics/devguides/collection/gajs/asyncMigrationExamples#migrationInstructions">Migrating to Async Tracking</a>
</p>
<h2>Operation</h2>
<p>
The filter looks for a Google Analytics snippet such as the following:
</p>
<pre class="prettyprint">
&lt;script type="text/javascript"&gt;
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src=" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
try {
var pageTracker = _gat._getTracker("UA-XXXXX-X");
pageTracker._trackPageview();
} catch(err) {}
&lt;/script&gt;
</pre>
<p>
and rewrites such snippets in-place to:
</p>
<pre class="prettyprint">
&lt;script type='text/javascript'&gt;
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
<strong>GLUE_SCRIPT</strong>
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);
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
try {
var pageTracker = _modpagespeed_getRewriteTracker("UA-XXXXX-X");
pageTracker._trackPageview();
} catch(err) {}
&lt;/script&gt;
</pre>
<p>
where <strong><code>GLUE_SCRIPT</code></strong> is JavaScript that
defines the <code>_modpagespeed_getRewriteTracker</code> function to
return an object that maps all the methods of the synchronous API to
the asynchronous API.
</p>
<p>
Additionally, the filter will replace loads in the following format:
</p>
<pre class="prettyprint">
&lt;script src="http://www.google-analytics.com/ga.js" type="text/javascript"&gt;&lt;/script&gt;
</pre>
<p>
The rewrite is known to not work when calls are made to Google
Analytics methods that return values. To avoid this issue, the
filter searches for these methods and abandons the rewrite if
they are found.
</p>
<h3>Example</h3>
<p>
You can see the filter in action at <code>www.modpagespeed.com</code> on this
<a href="https://www.modpagespeed.com/examples/make_google_analytics_async.html?ModPagespeed=on&amp;ModPagespeedFilters=make_google_analytics_async">example</a>.
</p>
<h2>Requirements</h2>
<p>
In order for the filter to trigger, the Google Analytics snippets
must be in the same format as shown above. The filter only performs
simple string matches to find the Google Analytics snippets.
</p>
<p>
Also, once a synchronous load is matched, the rest of the page is scanned for
any Google Analytics calls that return values. It only performs the rewrite
once it has reached the end of the page. That means the filter depends on how
the web page is buffered by the server. Specifically, if the snippet is not
in the last flush window, it will not be rewritten.
</p>
<h2>Risks</h2>
<p>
This filter is considered high risk.
</p>
<p>
The <code>make_google_analytics_async</code> filter is experimental
and has not had extensive real-world testing. One case where a rewrite
would cause errors is if the filter misses calls to Google Analytics
methods that return values. If such methods are found, the rewrite is
skipped. However, the disqualifying methods will be missed if they
<ul style="margin-bottom: .5em">
<li>come before the load,</li>
<li>are in attributes such as "onclick",</li>
<li>or if they are in external resources.</li>
</ul>
Those cases are expected to be rare.
</p>
</div>
<!--#include virtual="_footer.html" -->
</body>
</html>