由于Google Analytics(分析)的原因,PageSpeed Insights 99/100可以缓存GA?


243

我正在寻求在PageSpeed上达到100/100,而且我快到了。我正在尝试找到一个很好的解决方案来缓存Google Analytics(分析)。

这是我收到的消息:

利用浏览器缓存在静态资源的HTTP标头中设置到期日期或最长期限,可以指示浏览器从本地磁盘而不是通过网络加载以前下载的资源。利用浏览器对以下可缓存资源进行缓存:http : //www.google-analytics.com/analytics.js(2小时)

我找到的唯一解决方案是从2012年开始的,我认为这不是一个好的解决方案。本质上,您可以复制GA代码并自己托管。然后,您每天执行一次cron作业来重新检查Google,以获取最新的GA代码并进行替换。

http://diywpblog.com/leverage-browser-cache-optimize-google-analytics/

在使用Google Analytics(分析)时,我还能做什么达到100/100?

谢谢。


1
我使用了cron方法,没有cron的使用(加载并缓存onload。如果需要,我可以共享php代码)。而且我修正了我的GA修正建议。但是这里没有什么问题:我留下了“ Cache-Control:max-age = 604800”标头。这比5分钟缓存要高得多。
罗曼·洛舍夫

6
不过,这真的是个好主意吗?在服务器上缓存此文件意味着浏览器将不得不重新下载该文件,而不是通过使用Google Analytics(分析)访问其他网站来重新使用已经缓存的文件。因此,它实际上可能会稍微降低访问者的速度。
s427

Answers:


240

好吧,如果Google在欺骗您,您可以欺骗Google:

这是pageSpeed的用户代理:

“Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.8 (KHTML, like Gecko; Google Page Speed Insights) Chrome/19.0.1084.36 Safari/536.8”

您可以插入条件以避免将分析脚本提供给PageSpeed:

<?php if (!isset($_SERVER['HTTP_USER_AGENT']) || stripos($_SERVER['HTTP_USER_AGENT'], 'Speed Insights') === false): ?>
// your analytics code here
<?php endif; ?>

显然,它并没有任何实质性的改善,但是如果您唯一关心的是获得100/100的分数,那就可以了。


4
聪明……可惜,我使用边缘缓存,因为该脚本仅在请求到达每个请求的源时才起作用:(
Amy Neville

49
然后通过JS加载它:)if(navigator.userAgent.indexOf("Speed Insights") == -1) { /* analytics here */ }
半疯狂(2014年

1
@Jim请参阅stackoverflow.com/questions/10734968/…-您将{ }在我的示例中使用此方法,以及GA使用的任何其他JS(例如,ga('create', 'UA-XXXXX-Y', 'auto'); ga('send', 'pageview');或其他)
2014年

1
@Jim我已经添加了一个涵盖此内容的答案。
半疯狂

6
警告:这不再起作用。由Lighthouse强力驱动的Page Speed Insights使用默认的userAgent,该用户不再能被检测到。
David Vielhuber

39

有一个名为ga-lite的Google Analytics(分析)js库的子集,您可以根据需要缓存。

该库使用Google Analytics(分析)的公共REST API将用户跟踪数据发送给Google。您可以从有关ga-lite的博客文章中了解更多信息

免责声明:我是这个图书馆的作者。我在这个特定的问题上苦苦挣扎,发现的最好结果是实施了该解决方案。


21

这是一个使用JS进行基本GA跟踪的非常简单的解决方案,该解决方案也适用于边缘缓存/代理(这是从注释转换而来的):

if(navigator.userAgent.indexOf("Speed Insights") == -1) {
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-XXXXXXXXX-X', 'auto');
  ga('send', 'pageview');
}

注意:这是默认的GA脚本。您可能有其他ga()呼叫,如果是这样,则需要在致电之前始终检查用户代理ga(),否则可能会出错。


2
对“注:”部分做出反应,您可以gaga = function(){};在代码段之前声明的那样在执行时以静默方式失败,ga();因此您不必在代码中的所有位置检查此函数的存在。
伊斯特万·帕林卡斯(IstvánPálinkás)

1
如何在脚本<script async src =“ googletagmanager.com/gtag/js?id=UA-xx6600xx-1" > </… >中添加此内容
Navnish Bhardwaj,

16

我不会担心。请勿将其放在您自己的服务器上,这听起来像是Google的问题,但效果还不错。将文件放在您自己的服务器上会产生许多新问题。

他们可能需要每次都调用该文件,而不是从客户端的缓存中获取该文件,因为那样一来您就无需计算访问次数。

如果您对此感到不满意,请在Google洞察力本身上运行Google洞察力URL,笑着,放松一下并继续进行工作。


68
他想知道他怎么能达到100,而不是99。
Erick Engelhardt,2015年

4
这个答案不正确,从中下载Analytics.js文件不会影响分析跟踪。托管自己的分析文件的问题是,您始终必须手动更新到最新版本(一年几次)。
马修·多尔曼

1
感谢马修指出。显然我错了,这很好,但是仍然不认为在您自己的服务器上托管此文件不是一个好主意,因为我可以想象它会带来很多新问题。OP的问题是如何在pagespeed上达到100,而我的答案不是担心达到100。这可能是一个非常烦人的答案,但这就是我。
Leo Muller

3
对于那些认为99还不够的人来说,这是一个很好的答案。更好地将时间花在解决实际问题上。
linqu

@ErickEngelhardt你是正确的,但是如果人们问一个问题,即您认为自己的目标不是最佳目标,那么您应该给他们一个提示,哪种解决方案可能会更好地为他们服务。
观察者

10

在Google文档中,他们确定了一个pagespeed将异步加载脚本的过滤器:

ModPagespeedEnableFilters make_google_analytics_async

您可以在以下位置找到文档:https : //developers.google.com/speed/pagespeed/module/filter-make-google-analytics-async

需要强调的一件事是过滤器被认为是高风险的。从文档:

make_google_analytics_async过滤器是实验性的,尚未进行广泛的实际测试。重写会导致错误的一种情况是,如果过滤器错过了对返回值的Google Analytics(分析)方法的调用。如果找到了这样的方法,则跳过重写。但是,如果取消资格的方法在加载之前出现,在诸如“ onclick”之类的属性中或者在外部资源中,则会被取消。预计这些情况很少见。


7

varvy.com100/100 Google页面速​​度分析)仅在用户滚动页面时才加载google analitycs代码:

var fired = false;

window.addEventListener("scroll", function(){
    if ((document.documentElement.scrollTop != 0 && fired === false) || (document.body.scrollTop != 0 && fired === false)) {

        (function(i,s,o,g,r,a,m{i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-XXXXXXXX-X', 'auto');
        ga('send', 'pageview');

        fired = true;
    }
}, true);

7
如果访问者不滚动但仅单击一个链接,该怎么办。他将不会被计入分析。
Ross Ivantsiv

@RossIvantsiv您还可以处理单击!
ar099968 '18


6

存储localy analytics.js,但Google不建议这样做:https : //support.google.com/analytics/answer/1032389?hl=zh_CN

不建议您这样做,因为google可以在需要时更新脚本,因此只需执行一个每周下载分析javascript的脚本,您就不会遇到麻烦!

顺便说一下,此解决方案可防止adblock阻止Google Analytics(分析)脚本


它并没有完全绕过Adblock(它仍然阻止ajax调用),但是至少您获得了会话和页面浏览量
NiloVelez

5

您可以通过自己的服务器代理Google Analytics(分析)脚本,将其保存在本地,并每小时自动更新文件,以确保该文件始终是Google的最新版本。

我已经在几个站点上做到了,而且一切正常。

NodeJS / MEAN Stack中的Google Analytics(分析)代理路由

这就是我在使用MEAN堆栈构建的博客上实现它的方式。

router.get('/analytics.js', function (req, res, next) {
    var fileUrl = 'http://www.google-analytics.com/analytics.js';
    var filePath = path.resolve('/content/analytics.js');

    // ensure file exists and is less than 1 hour old
    fs.stat(filePath, function (err, stats) {
        if (err) {
            // file doesn't exist so download and create it
            updateFileAndReturn();
        } else {
            // file exists so ensure it's not stale
            if (moment().diff(stats.mtime, 'minutes') > 60) {
                updateFileAndReturn();
            } else {
                returnFile();
            }
        }
    });

    // update file from remote url then send to client
    function updateFileAndReturn() {
        request(fileUrl, function (error, response, body) {
            fs.writeFileSync(filePath, body);
            returnFile();
        });
    }

    // send file to client
    function returnFile() {
        res.set('Cache-Control', 'public, max-age=' + oneWeekSeconds);
        res.sendFile(filePath);
    }
});

ASP.NET MVC中的Google Analytics(分析)代理操作方法

这就是我在使用ASP.NET MVC构建的其他网站上实现它的方式。

public class ProxyController : BaseController
{
    [Compress]
    public ActionResult GoogleAnalytics()
    {
        var fileUrl = "https://ssl.google-analytics.com/ga.js";
        var filePath = Server.MapPath("~/scripts/analytics.js");

        // ensure file exists 
        if (!System.IO.File.Exists(filePath))
            UpdateFile(fileUrl, filePath);

        // ensure file is less than 1 hour old
        var lastModified = System.IO.File.GetLastWriteTime(filePath);
        if((DateTime.Now - lastModified).TotalMinutes > 60)
            UpdateFile(fileUrl, filePath);

        // enable caching for 1 week for page speed score
        Response.AddHeader("Cache-Control", "max-age=604800");

        return JavaScript(System.IO.File.ReadAllText(filePath));
    }

    private void UpdateFile(string fileUrl, string filePath)
    {
        using (var response = WebRequest.Create(fileUrl).GetResponse())
        using (var dataStream = response.GetResponseStream())
        using (var reader = new StreamReader(dataStream))
        {
            var body = reader.ReadToEnd();
            System.IO.File.WriteAllText(filePath, body);
        }
    }
}

这是MVC ProxyController用于Gzip压缩的CompressAttribute

public class CompressAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {

        var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
        if (string.IsNullOrEmpty(encodingsAccepted)) return;

        encodingsAccepted = encodingsAccepted.ToLowerInvariant();
        var response = filterContext.HttpContext.Response;

        if (encodingsAccepted.Contains("gzip"))
        {
            response.AppendHeader("Content-encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
        else if (encodingsAccepted.Contains("deflate"))
        {
            response.AppendHeader("Content-encoding", "deflate");
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
    }
}

更新了Google Analytics(分析)脚本

在客户端,我会在分析路径上附加当前日期(直到一小时),以使浏览器使用的缓存版本不会超过一个小时。

<!-- analytics -->
<script>
    (function (i, s, o, g, r, a, m) {
        i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
            (i[r].q = i[r].q || []).push(arguments)
        }, i[r].l = 1 * new Date(); a = s.createElement(o),
        m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
    })(window, document, 'script', '/analytics.js?d=' + new Date().toISOString().slice(0, 13), 'ga');
</script>


4

的PHP

在您的HTML或PHP代码中添加此代码:

<?php if (!isset($_SERVER['HTTP_USER_AGENT']) || stripos($_SERVER['HTTP_USER_AGENT'], 'Speed Insights') === false): ?>
  <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-PUT YOUR GOOGLE ANALYTICS ID HERE', 'auto');
    ga('send', 'pageview');
  </script>
<?php endif; ?>

的JavaScript

使用JavaScript可以正常工作:

  <script>
  if(navigator.userAgent.indexOf("Speed Insights") == -1) {
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-<PUT YOUR GOOGLE ANALYTICS ID HERE>', 'auto');
    ga('send', 'pageview');
  }
  </script>

NiloVelez已经说过:显然,它并没有任何实质性的改善,但是如果您唯一关心的是获得100/100的分数,那就可以了。



0

Google 告诫不要使用分析脚本的本地副本。但是,如果执行此操作,则可能要使用插件和调试脚本的本地副本。

主动缓存的第二个问题是,您将从缓存页面中获得匹配-页面可能已更改或已从网站中删除。


0

要解决此问题,您必须在本地下载文件并运行cron作业以保持更新。注意:这根本不能使您的网站更快,因此最好忽略它。

但是,出于演示目的,请遵循以下指南:http : //diywpblog.com/leverage-browser-cache-optimize-google-analytics/


“这并不能使您的网站更快”,这不一定是正确的。从理论上讲,由于共享字典,将包含分析的文件gzip压缩到非关键级联的JS文件后,其压缩程度应比单独的分析文件略小。也许麻烦多于其价值。
雷·福斯

0

这可能会解决问题:)

<script>
  $.ajax({
  type: "GET",
  url: "https://www.google-analytics.com/analytics.js",
  success: function(){},
  dataType: "script",
  cache: true
  });
</script>

0

根据您对Google Analytics(分析)数据的使用情况,如果您需要基本信息(例如访问,UI交互),则可能根本不包括analytics.js,但仍可以在GA中收集数据。

一种选择可能是改为在缓存的脚本中使用测量协议。 Google Analytics(分析):测量协议概述

将传输方法显式设置为image时,您可以看到GA如何构造自己的图像信标。

ga('set', 'transport', 'image');

https://www.google-analytics.com/r/collect
  ?v={protocol-version}
  &tid={tracking-id}
  &cid={client-id}
  &t={hit-type}
  &dl={location}

您可以使用所需的有效负载创建自己的GET或POST请求。

但是,如果您需要更多细节,那可能就不值得您付出努力。


与Pagespeed的连接在哪里?
Nico Haase

通过不加载analytics.js,可以避免页面速度损失。
乔纳森

是的 通过跳过页面中所有的CSS,JS和图像,它的加载速度甚至更快。根据OP,不可以跳过Google Analytics(分析)
Nico Haase

除了数据仍记录在Google Analytics(分析)中之外,我认为我的回答是正确的,并且明确指出,根据Google Analytics(分析)要求的详细程度,可能值得考虑的一个选项是,重要的是仍会记录访问,UI交互和其他可能的指标。如果OP希望针对最终的1%进行优化,则可能是值得考虑的优化。
乔纳森

@NicoHaase我已经编辑了评论,希望可以使我的观点更加清楚。有兴趣听听您的想法。
乔纳森

0

您可以设置以www.google-analytics.com作为原始服务器的Cloudfront发行版,并在Cloudfront发行版设置中设置更长的到期标头。然后在Google代码段中修改该域。这样可以避免您自己的服务器上的负载以及在cron作业中不断更新文件的需要。

这是设置并忘记了。因此,如果有人“复制”您的代码段并窃取您的带宽,您可能需要向Cloudfront添加计费警报。

编辑:我试过了,这不是那么容易,Cloudfront传递Cache-Control标头没有简单的方法来删除它


0

在新标签页中打开https://www.google-analytics.com/analytics.js文件,复制所有代码。

现在,在您的网络目录中创建一个文件夹,将其重命名为google-analytics。

在同一文件夹中创建一个文本文件,然后粘贴您上面复制的所有代码。

重命名文件ga-local.js

现在,更改URL,以在Google Analytics(分析)代码中调用您本地托管的Analytics脚本文件。它看起来像这样,即https://domain.xyz/google-analytics/ga.js

最后,将您的Google新Google Analytics(分析)代码放到网页的页脚中。

你已准备好出发。现在,检查您的Google PageSpeed Insights网站。它不会显示有关利用浏览器缓存Google Analytics(分析)的警告。这种解决方案的唯一问题是,要定期手动更新Analytics脚本。


0

在2020年,Page Speed Insights用户代理为:移动版“ Chrome灯塔”和台式机版“ Google Page Speed Insights”。

<?php if (!isset($_SERVER['HTTP_USER_AGENT']) || stripos($_SERVER['HTTP_USER_AGENT'], 'Chrome-Lighthouse') === false  || stripos($_SERVER['HTTP_USER_AGENT'], 'Google Page Speed Insights') === false): ?>
// your google analytics code and other external script you want to hide from PageSpeed Insights here
<?php endif; ?>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.