PageSpeed ​​Insights 99/100 por causa do Google Analytics - Como posso armazenar em cache o GA?

243

Estou em uma missão para atingir 100/100 no PageSpeed ​​e estou quase lá. Estou tentando encontrar uma boa solução para armazenar em cache o Google Analytics.

Aqui está a mensagem que recebo:

Aproveitar o cache do navegador A configuração de uma data de validade ou uma idade máxima nos cabeçalhos HTTP para recursos estáticos instrui o navegador a carregar recursos baixados anteriormente do disco local em vez da rede. Aproveite o cache do navegador para os seguintes recursos que podem ser armazenados em cache: http://www.google-analytics.com/analytics.js (2 horas)

A única solução que encontrei foi em 2012 e não acho que seja uma boa solução. Essencialmente, você copia o código do GA e o hospeda por conta própria. Em seguida, você executa um trabalho cron para verificar novamente o Google uma vez por dia para pegar o código GA mais recente e substituí-lo.

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

O que mais posso fazer para atingir 100/100 enquanto também uso o Google Analytics?

Obrigado.

sjmartin
fonte
1
Eu usei o método cron, sem o uso do cron (carrega e armazena em cache. Eu posso compartilhar o código php, se quiser). E eu corrigi minha sugestão de correção do GA. Mas pouco problema ficou por aí: eu deixei o cabeçalho "Cache-Control: max-age = 604800". O que é muito maior que o cache de 5 minutos.
Roman Losev
6
É realmente uma boa ideia? O armazenamento em cache desse arquivo no servidor significa que o navegador precisará fazer o download novamente em vez de reutilizar o que já foi armazenado em cache, visitando outros sites usando o Google Analytics. Por isso, pode realmente atrasar um pouco os visitantes.
S427 09/07/2015
Possível duplicata do cache
Joe

Respostas:

240

Bem, se o Google está traindo você, você pode enganar o Google de volta:

Este é o agente do usuário para o 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”

Você pode inserir um condicional para evitar veicular o script de análise no PageSpeed:

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

Obviamente, isso não fará nenhuma melhoria real, mas se sua única preocupação é obter uma pontuação de 100/100, isso o fará.

NiloVelez
fonte
4
Inteligente ...... pena que eu uso caching vantagem porque este script só irá funcionar se os pedidos chegar a sua origem para cada pedido :(
Amy Neville
49
Carregá-lo via JS, em seguida, :) :)if(navigator.userAgent.indexOf("Speed Insights") == -1) { /* analytics here */ }
Half Crazed
1
@ Jim Consulte stackoverflow.com/questions/10734968/… - você usaria esse método dentro do { }exemplo, juntamente com qualquer outro JS que o GA use (como o que ga('create', 'UA-XXXXX-Y', 'auto'); ga('send', 'pageview');seja)
Half Crazed
1
@ Jim Adicionei uma resposta que cobre isso.
Half Crazed
6
Aviso: isso não funciona mais. O Page Speed ​​Insights da Lighthouse usa um userAgent padrão, que não pode mais ser detectado.
David Vielhuber 20/01/19
39

Há um subconjunto da biblioteca js do Google Analytics chamado ga-lite que você pode armazenar em cache da maneira que desejar.

A biblioteca usa a API REST pública do Google Analytics para enviar os dados de rastreamento do usuário ao Google. Você pode ler mais na postagem do blog sobre ga-lite .

Disclaimer: Eu sou o autor desta biblioteca. Lutei com esse problema específico e o melhor resultado que encontrei foi implementar esta solução.

jehna1
fonte
21

Aqui está uma solução realmente simples usando JS, para rastreamento básico do GA, que também funcionará para caches / proxies de borda (isso foi convertido a partir de um comentário):

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');
}

Nota: este é o script GA padrão. Você pode ter outras ga()chamadas e, nesse caso, sempre precisará verificar o agente do usuário antes de ligar ga(), caso contrário, poderá ocorrer um erro.

Meio enlouquecido
fonte
2
Reagindo à seção "Nota:", você pode declarar gacomo ga = function(){};antes do trecho falhar silenciosamente quando executado, ga();para não precisar verificar a existência dessa função em todo o código.
István Pálinkás
1
Como adicionar isso no script <script async src = " googletagmanager.com/gtag/js?id=UA-xx6600xx-1 " > </… >
Navnish Bhardwaj
16

Eu não me importaria com isso. Não o coloque no seu próprio servidor, parece que esse é um problema do Google, mas é o melhor possível. Colocar o arquivo em seu próprio servidor criará muitos problemas novos.

Eles provavelmente precisam que o arquivo seja chamado todas as vezes, em vez de obtê-lo do cache do cliente, pois dessa forma você não contaria as visitas.

Se você tiver algum problema para se sentir bem com isso, execute o URL do Google Insights no próprio Google Insights, ria, relaxe e continue seu trabalho.

Leo Muller
fonte
68
Ele quer saber como pode chegar a 100, e não se 99 estiver ok.
Erick Engelhardt
4
Esta resposta não é verdadeira, onde o arquivo Analytics.js é baixado não afeta se as faixas de análise são ou não. O problema de hospedar seu próprio arquivo de análise é que você sempre precisa atualizar manualmente para a versão mais recente (algumas vezes por ano).
precisa
1
Obrigado Matthew por apontar isso. Aparentemente, eu estava errado, o que é bom, mas ainda não acho uma boa idéia hospedar esse arquivo em seu próprio servidor, porque posso imaginar que isso criará muitos problemas novos. A questão do OP era como chegar a 100 na velocidade da página e minha resposta não é se preocupar em chegar a 100. Essa pode ser uma resposta realmente irritante, mas sou eu.
Leo Muller
3
uma boa resposta para as pessoas que se perderam pensando 99 não é suficiente. dedique melhor seu tempo a problemas reais.
linqu 11/01
@ErickEngelhardt Você está certo, mas se as pessoas fizerem uma pergunta em que você acha que não estão buscando o melhor objetivo, você deve avisar a eles que solução pode servi-las melhor.
observador
10

Nos documentos do Google, eles identificaram um pagespeedfiltro que carregará o script de forma assíncrona:

ModPagespeedEnableFilters make_google_analytics_async

Você pode encontrar a documentação aqui: https://developers.google.com/speed/pagespeed/module/filter-make-google-analytics-async

Uma coisa a destacar é que o filtro é considerado de alto risco. Dos documentos:

O filtro make_google_analytics_async é experimental e não teve extensos testes no mundo real. Um caso em que uma reescrita causaria erros é se o filtro perder chamadas para métodos do Google Analytics que retornam valores. Se tais métodos forem encontrados, a reescrita será ignorada. No entanto, os métodos de desqualificação serão perdidos se vierem antes do carregamento, estiverem em atributos como "onclick" ou se estiverem em recursos externos. Espera-se que esses casos sejam raros.

Cameron Scott
fonte
7

varvy.com ( 100/100 insight de velocidade da página do Google ) carrega o código do google analitycs somente se o usuário fizer um scroll da página:

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);
ar099968
fonte
7
E se o visitante não rolar, mas apenas clicar em um link. Ele não será contado em análises.
Ross Ivantsiv
@RossIvantsiv você também pode lidar com o clique!
Ar099968
6

armazene localy analytics.js, mas não é recomendado pelo google: https://support.google.com/analytics/answer/1032389?hl=pt-BR

não é recomendado, pois o google pode atualizar o script quando quiserem; basta fazer um script que faça o download do javascript do analytics a cada semana e você não terá problemas!

A propósito, esta solução evita que o adblock bloqueie os scripts do Google Analytics

Froggiz
fonte
Não faz desvio Adblock completamente (ainda bloqueia chamadas AJAX), mas pelo menos você começa sessões e page views
NiloVelez
5

Você pode fazer proxy do script do google analytics por meio de seu próprio servidor, salvá-lo localmente e atualizar automaticamente o arquivo a cada hora para garantir que seja sempre a versão mais recente do google.

Já fiz isso em alguns sites agora e tudo está funcionando bem.

Rota do proxy do Google Analytics na pilha NodeJS / MEAN

É assim que eu o implementei no meu blog criado com a pilha 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);
    }
});

Método de ação de proxy do Google Analytics no ASP.NET MVC

É assim que eu o implementei em outros sites criados com o 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);
        }
    }
}

Este é o CompressAttribute usado pelo MVC ProxyController para compactação Gzip

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);
        }
    }
}

Script do Google Analytics atualizado

No lado do cliente, anexo o caminho do analytics com a data atual até a hora, para que o navegador não use uma versão em cache com mais de uma hora.

<!-- 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>
Jason
fonte
4

PHP

Adicione isso no seu código HTML ou 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

Isso funciona bem com 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 já disse: Obviamente, isso não fará nenhuma melhoria real, mas se sua única preocupação é obter uma pontuação de 100/100, isso o fará.

Suriyaa
fonte
1

tente isso basta inserir antes

<script async='async' src='https://cdn.jsdelivr.net/ga-lite/latest/ga-lite.min.js'></script> <script>var galite=galite||{};galite.UA="xx-xxxxxxx-x";</script>

Altere xx-xxxxxxx-x para o seu código, verifique a implementação aqui http://www.gee.web.id/2016/11/how-to-leverage-browser-caching-for-google-analitycs.html

Gee
fonte
1
Esteja ciente de que isso é para ga-lite, em vez das análises padrão
Rob Forrest
0

O Google adverte contra o uso de cópias locais dos scripts analíticos. No entanto, se você estiver fazendo isso, provavelmente desejará usar cópias locais dos plugins e do script de depuração.

Uma segunda preocupação com o cache agressivo é que você receberá hits de páginas em cache - que podem ter sido alteradas ou removidas do site.

Oren Bochman
fonte
0

Para corrigir esse problema, você teria que baixar o arquivo localmente e executar um trabalho cron para manter a atualização. Nota: isso não torna seu site mais rápido, então é melhor ignorá-lo.

No entanto, para fins de demonstração, siga este guia: http://diywpblog.com/leverage-browser-cache-optimize-google-analytics/

Mo Beigi
fonte
"isso não torna seu site mais rápido", o que não é necessariamente verdade. Como em teoria, compactar um JS concatenado não crítico em um arquivo com análise incluída deve compactar um pouco menor que um arquivo de análise separado por causa do dicionário compartilhado. Talvez mais problemas do que valha a pena.
22416 Ray Foss
0

Isso pode fazer o truque :)

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

Dependendo do uso dos dados do Google Analytics, se você quiser informações básicas (como visitas, interações da interface do usuário), poderá não incluir o analytics.js, mas ainda assim coletar dados no GA.

Uma opção pode ser usar o protocolo de medição em um script em cache. Google Analytics: visão geral do protocolo de avaliação

Quando você define explicitamente o método de transporte como imagem, pode ver como o GA constrói seus próprios beacons de imagem.

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}

Você pode criar suas próprias solicitações GET ou POST com a carga útil necessária.

No entanto, se você precisar de um nível maior de detalhes, provavelmente não valerá o seu esforço.

Jonathan
fonte
Onde está a conexão com o Pagespeed?
Nico Haase
Ao não carregar o analytics.js, você evita a penalidade de velocidade da página.
19617 Jonathan
Sim. E ignorando todo o CSS, JS e imagens da sua página, o carregamento será ainda mais rápido. Ignorar o Google Analytics não é uma opção, de acordo com o OP
Nico Haase
Exceto que os dados ainda estão registrados no Google Analytics, acho que minha resposta é válida e afirmou claramente que, dependendo do nível de detalhe exigido pelo Google Analytics, pode ser uma opção que vale a pena considerar, o que ainda é importante para registrar visitas, interações da interface do usuário e potencialmente outras métricas . Se o OP estiver buscando otimizar os 1% finais, pode ser uma otimização que vale a pena considerar.
Jonathan
@NicoHaase Eu editei meu comentário para, com sorte, tornar meu argumento mais claro. Interessado em ouvir seus pensamentos.
Jonathan
0

Você pode configurar uma distribuição em nuvem que tenha www.google-analytics.com como servidor de origem e definir um cabeçalho de expiração mais longo nas configurações de distribuição em nuvem. Em seguida, modifique esse domínio no snippet do Google. Isso evita a carga no seu próprio servidor e a necessidade de continuar atualizando o arquivo em uma tarefa cron.

Isso é configuração e esqueça. Portanto, convém adicionar um alerta de cobrança à nuvem, caso alguém "copie" seu snippet e roube sua largura de banda ;-)

Edit: Eu tentei e não é tão fácil, o Cloudfront passa pelo cabeçalho de controle de cache sem uma maneira fácil de removê-lo

Jan M
fonte
0

Abra o arquivo https://www.google-analytics.com/analytics.js em uma nova guia e copie todo o código.

Agora crie uma pasta no seu diretório da web e renomeie para google analytics.

Crie um arquivo de texto na mesma pasta e cole todo o código que você copiou acima.

Renomeie o arquivo ga-local.js

Agora altere o URL para chamar seu arquivo de script do Analytics hospedado localmente no seu código do Google Analytics. Será algo parecido com isto, por exemplo, https://domain.xyz/google-analytics/ga.js

Por fim, coloque seu NOVO código do Google Analytics no rodapé da sua página da web.

Você está pronto para ir. Agora verifique seu site do Google PageSpeed ​​Insights. Ele não mostrará o aviso para alavancar o cache do navegador no Google Analytics. E o único problema com esta solução é atualizar regularmente o Script do Analytics manualmente.

Formal
fonte
0

Em 2020, os agentes de usuários do Page Speed ​​Insights são: "Chrome-Lighthouse" para celular e "Google Page Speed ​​Insights" para desktop.

<?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; ?>
Eduard Dimitrov
fonte
-13

Você pode minificar todos os seus scripts na página, incluindo o analytics.jsuso de:

Lembre-se de minificar os arquivos antes de usá-lo. Caso contrário, consumirá mais tempo de processamento.

Erick Engelhardt
fonte
6
analytics.js já está minificado a partir da fonte
João Pimentel Ferreira