Analytics

17 jun, 2015

Medindo o uso do breakpoint responsivo de um site

Publicidade

A maioria das ferramentas de analytics na web vai te fornecer um monte de informações sobre os dispositivos de seus usuários. Esses insights podem ser extremamente úteis para medir as tendências e são particularmente importantes se você tiver sites mobile e desktop separados ou um design diferente para Android e iOS. Mas se você construiu o seu site de forma responsiva, as informações do dispositivo simplesmente não contam toda a história.

O design responsivo pretende se divorciar do dispositivo ou dos elementos específicos da plataforma. Em vez disso, ele se adapta às propriedades do dispositivo agnóstico como o tamanho da tela, a densidade de pixels e a orientação do dispositivo.

Se o seu site foi construído em princípios deviceless (sem considerar o dispositivo), mas seu uso é medido contra as métricas apenas de dispositivo, você vai obter uma incompatibilidade – potencialmente das grandes.

O problema do dispositivo

Para ilustrar esse problema, vamos considerar o iPhone. A gama de tamanhos de tela do iPhone pode ir de 320 pixels em um iPhone 5s no modo retrato para 960 pixels em um iPhone 6 Plus no modo paisagem. Isso é uma gama enorme. Na verdade, no meu site, a gama abrange, no total, quatro dos cinco breakpoints.

Se você quiser recolher todas as informações úteis sobre a eficácia de um projeto em um breakpoint em particular, você não pode fazer isso apenas com os dados do dispositivo. Em suma, sites construídos de forma responsiva devem medir o uso de breakpoints, além do uso do dispositivo.

Se as nossas metodologias de projeto pretendem ser agnósticas a dispositivo, por que tantas das nossas ferramentas de anlytics estão tão focadas no dispositivo? A resposta, claro, é que essas ferramentas não sabem como você construiu seu site, as media queries que você gosta ou o que nome você escolheu para eles.

Felizmente, ferramentas como o Google Analytics permitem que você envie dimensões e métricas personalizadas para acompanhar exatamente esse tipo de dados específicos do usuário.

Nota: o resto deste artigo explica como medir o uso do breakpoint no Google Analytics, porém os conceitos e os exemplos de código devem ser aplicados a outras plataformas também.

Dimensões e métricas personalizadas

No Google Analytics, uma métrica é uma interação que pode ser contada ou quantificada. As métricas comuns são coisas como os usuários (o número de visitantes que chegaram ao seu site), as sessões (o número de visitas realizadas pelos visitantes), e visualizações de página (o número de páginas que os visitantes viram). Uma vez que as métricas são quantificáveis, elas são sempre um tipo de dados numéricos.

As dimensões são como você subdivide as suas métricas em categorias relevantes. Por exemplo, se a sua métrica for visualizações de página, você pode querer subdividi-las pelo caminho da página ou pelo título. Da mesma forma, se a sua métrica for usuários, você pode desejar subdividi-los pelo navegador ou pela localização geográfica. As dimensões são normalmente strings, mas elas podem ser outros tipos de dados, como números ou datas.

Dito isso, é esperado que você queira acompanhar os breakpoints responsivos como uma dimensão personalizada. Se o seu site teve 1.000 visualizações de página na terça-feira, você pode estar curioso para saber quantas dessas páginas foram exibidas no menor contra o maior breakpoint. Para praticamente qualquer métrica com a qual você se preocupe (usuários, sessões, visualizações de página etc.), é importante saber qual breakpoint responsivo estava ativo na hora da interação.

Se você nunca criou uma dimensão personalizada no Google Analytics, pode seguir estas instruções da Central de Ajuda do Google Analytics. Eu escolhi chamar a minha dimensão personalizada de “breakpoint” (você pode escolher o nome que quiser), e uma vez que que sei que o breakpoint ativo é útil para praticamente qualquer interação, selecionei o escopo “hit”.

Depois de criar a dimensão personalizada, você pode usá-la apenas como utilizaria qualquer outra dimensão.

Rastreando breakpoints com Google Analytics

O Google Analytics usa a biblioteca analytics.js para enviar dados para o back-end do Google Analytics. Se já tiver usado o analytics.js, você provavelmente já viu este código antes:

ga('create', 'UA-XXXX-Y', 'auto');
ga('send', 'pageview');

Embora este artigo não pretenda ser um tutorial sobre analytics.js, eu considero importante entender o básico do que está acontecendo, especialmente quando você começar a implementar os recursos mais avançados.

O código acima faz duas coisas. Primeiro, ele cria um objeto de rastreamento e, em seguida, envia um hit da visualização para o Google Analytics. A coisa importante para se entender é que quando você cria um novo objeto de rastreamento em analytics.js, o rastreador, na instanciação, recolhe um monte de informações importantes sobre o contexto atual de navegação, por exemplo, o título da página, a URL na barra de endereços, o tamanho da tela e a janela etc. Estas são, com efeito, suas dimensões.

A segunda coisa que o código faz é enviar um hit de visualização de página para o Google Analytics. Sempre que você enviar um hit para o Google Analytics, ele envia todos os dados de contexto atualmente armazenados no rastreador junto com esse hit. Isso significa que se você quiser acompanhar as informações do breakpoint, precisa descobrir qual breakpoint está ativo no momento e armazenar essas informações sobre o rastreador antes de enviar todos os acessos ao Google Analytics.

Para descobrir qual breakpoint está ativo, você pode usar o método matchMedia:

var mql = window.matchMedia('(min-width: 400px)');

if (mql.matches) {
  // The viewport width is greater than or equal to 400px.
}
else {
  // The viewport width is less than 400px.
}

O método matchMedia retorna um objeto MediaQueryList, o qual possui uma propriedade matches. Observe que esse objeto está “live”, o que significa que a propriedade matches será atualizada automaticamente quando você mudar o tamanho da janela ou a orientação do dispositivo. Isso significa que você só precisa instanciar um objeto MediaQueryList por breakpoint.

Definindo breakpoints como dimensões

Dependendo de como você escrever suas media queries, pode haver mais do que uma correspondência de cada vez. Se você usar uma abordagem mobile-first (como meu site faz), seus estilos de base não usam regras @media e se aplicam a todos os tamanhos de viewport. A tamanhos maiores do viewport se aplicam regras adicionais, conforme necessário. Com tamanhos de tela muito grandes, todas as suas media queries baseadas em tamanho combinarão ao mesmo tempo.

Isso é bom para o CSS, mas a partir de uma perspectiva de analytics, uma dimensão só pode ter um único valor. Obviamente, você não gostaria de ter uma visualização de página associada com o /about da página e o /contact da página simultaneamente. Da mesma forma, você deve escrever seu código para que apenas uma dimensão de breakpoint corresponda ao mesmo tempo. [1]

No momento da redação deste artigo, meu site define os seguintes breakpoints no CSS:

sm : (min-width: 420px)
md : (min-width: 570px)
lg : (min-width: 800px)
xl : (min-width: 1000px)

Há duas coisas que valem a pena reparar aqui. Em primeiro lugar, quando a largura do viewport for menor do que 420 pixels, nenhuma media query irá combinar. Em segundo lugar, quando o viewport for maior do que 1.000 pixels, todas essas media queries irão corresponder.

Para que eu apenas relatasse um breakpoint correspondente de cada vez, eu precisava ajustar suas definições no meu código JavaScript. Eu os reescrevi da seguinte forma:

var breakpoints = {
  xs: '(max-width: 419px)',
  sm: '(min-width: 420px) and (max-width: 569px)',
  md: '(min-width: 570px) and (max-width: 799px)',
  lg: '(min-width: 800px) and (max-width: 999px)',
  xl: '(min-width: 1000px)'
};

Como você pode ver, eu adicionei um breakpoint “xs” para cobrir as larguras extremamente pequenas, e acrescentei uma lógica max-width nos breakpoints de média/middle para torná-los exclusivos.

Mídias correspondentes

Para descobrir qual breakpoint está combinando, você só itera sobre os itens em seu objeto breakpoints, cria uma instância MediaQueryList para cada um, e verifica a sua propriedade matches.

Dado o objeto breakpoint mostrado acima, é aqui como você pode encontrar o breakpoint ativo:

Object.keys(breakpoints).forEach(function(breakpoint) {
  var mql = window.matchMedia(breakpoints[breakpoint]);
  if (mql.matches) {
    // This breakpoint matches.
  }
});

Rastreando o breakpoint correspondente

Depois de saber qual breakpoint está combinando, você precisa atualizar o objeto de rastreamento. Para fazer isso no analytics.js, você chama o método set e o passa em uma chave e em um valor (ou um objeto de pares chave/valor).

ga('set', 'key', 'value');

Uma vez que estamos usando uma dimensão personalizada, a chave vai ser ‘dimensionN“, onde” N “é o índice do Google Analytics atribuído a essa dimensão personalizada no momento da criação (se essa for a primeira dimensão personalizada que você criou para a propriedade Google Analytics, será ‘dimension1‘).

O código acima torna-se agora (alterações em destaque):

Object.keys(breakpoints).forEach(function(breakpoint) {
  var mql = window.matchMedia(breakpoints[breakpoint]);
  if (mql.matches) {
    **ga('set', 'dimensionN', breakpoint);**
  }
});

Detectando mudanças do breakpoint

Além de saber qual breakpoint está ativo no carregamento, é importante também saber quando o breakpoint ativo muda. Se você não atualizar o objeto de rastreamento como à medida que o breakpoint ativo muda, todos os hits posteriores serão associados ao breakpoint errado (hits subsequentes poderiam ser algo como eventos personalizados, exceções, visitas sociais, ou visualizações de página dinamicamente carregadas em um aplicativo de uma única página).

Para detectar quando um objeto MediaQueryList corresponde às alterações de propriedade, você pode registrar um listener nele pelo método addListener:

var mql = window.matchMedia('(min-width: 400px)');

mql.addListener(function() {
  if (mql.matches) {
    // The viewport width is now greater than or equal to 400 pixels.
  }
  else {
    // The viewport width is now less than 400 pixels.
  }
});

Atualizando o tracker quando o breakpoint ativo muda

Para atualizar o breakpoint ativo armazenado no objeto de rastreamento, você pode adicionar listeners para cada objeto MediaQueryList já criado. Você precisa ter certeza e verificar se sua propriedade matches é verdadeira, pois as callbacks do listener são chamadas quando uma media query corresponde, bem como quando já não o faz.

Object.keys(breakpoints).forEach(function(breakpoint) {
  var mql = window.matchMedia(breakpoints[breakpoint]);

  // Set the initial breakpoint on page load.
  if (mql.matches) {
    ga('set', 'dimensionN', breakpoint);
  }

  // Update the breakpoint as the matched media changes.
  mql.addListener(function() {
    if (mql.matches) {
      ga('set', 'dimensionN', breakpoint);
    }
  });
});

Rastreando mudanças do breakpoint

Além de atualizar o rastreador, pode ser interessante saber com que frequência seus usuários mudam os breakpoints durante a navegação. A sabedoria convencional sugere que apenas tipos de desenvolvedores redimensionem a janela do navegador, mas você não está curioso para saber com certeza?

Você pode acompanhar as mudanças do breakpoint no Google Analytics usando o rastreamento de eventos. Os eventos geralmente têm uma categoria, ação e rótulo. No meu site, eu escolhi a categoria “breakpoint”, a ação “change”, e como rótulo o breakpoint atual é (por exemplo, “sm”, “md”, “lg” etc.).

Enviar um evento de hit que rastreia uma mudança do breakpoint pode ser feito assim:

ga('send', 'event', 'breakpoint', 'change', 'sm');

Você pode adicionar esse código de acompanhamento do evento para seus ouvintes de mudança existentes dos breakpoint. Certifique-se de atualizar o objeto de rastreamento com o novo breakpoint antes de enviar o evento, caso contrário, ele será associado ao breakpoint anterior.

Object.keys(breakpoints).forEach(function(breakpoint) {
  var mql = window.matchMedia(breakpoints[breakpoint]);

  // Set the initial breakpoint on page load.
  if (mql.matches) {
    ga('set', 'dimensionN', breakpoint);
  }

  // Update the breakpoint as the matched media changes.
  mql.addListener(function() {
    if (mql.matches) {
      ga('set', 'dimensionN', breakpoint);
      **ga('send', 'event', 'breakpoint', 'change', breakpoint);**
    }
  });
});

Tratando alterações rápidas

Se uma janela do navegador for redimensionada de pequena para grande (ou vice-versa) muito rapidamente, você provavelmente vai relatar vários eventos “change” que não são “real” e podem afetar negativamente a qualidade dos seus dados. Para evitar isso, você provavelmente vai querer fazer um limite de taxas nas suas chamadas de função para garantir que você só vai enviar um evento de alteração depois que todas as mudanças tiverem se instalado.

Esse limite de taxa pode ser feito através da adição de um salto de um segundo para a função listener de mudanças. No Inglês claro, isso significa que um hit só será enviado se outra mudança não for detectada no próximo segundo. Isso é implementado usando um setTimeout simples:

// Create a timeout reference in an external scope.
**var timeout;**

Object.keys(breakpoints).forEach(function(breakpoint) {
  var mql = window.matchMedia(breakpoints[breakpoint]);

  // Set the initial breakpoint on page load.
  if (mql.matches) {
    ga('set', 'dimensionN', breakpoint);
  }

  // Update the breakpoint as the matched media changes, and send an event.
  mql.addListener(function() {
    if (mql.matches) {
      **clearTimeout(timeout);**
      **timeout = setTimeout(function() {**
        ga('set', 'dimensionN', breakpoint);
        ga('send', 'event', 'breakpoint', 'change', breakpoint);
      **}, 1000);**
    }
  });
});

Relatório de uso de breakpoint

Eu não quero gastar muito tempo falando sobre como exibir seus dados de breakpoint no Google Analytics, mas uma vez que este artigo lida com dimensões personalizadas e como a elaboração de relatórios sobre as dimensões personalizadas é um tema um pouco avançado, eu acho que ele merece pelo menos uma menção.

Para visualizar os dados da dimensão personalizada que você coletou no Google Analytics, você precisará criar um relatório personalizado. Você pode fazer isso seguindo estas instruções. Quando perguntado, selecione um tipo de relatório “Explorer” ou “Table Flat”. A métrica que você vai escolher é com você (visualizações de página é provavelmente um bom começo), e a dimensão vai ser o que você nomeou sua dimensão personalizada.

Se você deseja criar um relatório personalizado que mostra os eventos de alteração breakpoint, use as métricas “Total Events”, a dimensão “Event Label” e adicione dois filtros de modo que “Event Category” seja “breakpoint” e “Event Action” seja “change”.

Como alternativa, você pode consultar a API de relatórios do Google Analytics Core para obter os mesmos dados. Os dois relatórios seguintes usam Query Explorer para acessar a API (estes assumem que a sua dimensão personalizada tem um índice de 1):

Encerrando

Se o seu site foi construído utilizando design responsivo, medir e compreender como os usuários estão interagindo com o seu site para os vários breakpoints é fundamental para a tomada de decisões informadas em um projeto no futuro.

E a implementação de rastreamento de breakpoint com serviços como o Google Analytics é bem simples. Aqui está o código final para implementar o rastreamento do breakpoint que combina todas as técnicas descritas neste artigo:

var timeout;
var breakpoints = {
  xs: '(max-width: 419px)',
  sm: '(min-width: 420px) and (max-width: 569px)',
  md: '(min-width: 570px) and (max-width: 799px)',
  lg: '(min-width: 800px) and (max-width: 999px)',
  xl: '(min-width: 1000px)'
};

Object.keys(breakpoints).forEach(function(breakpoint) {
  var mql = window.matchMedia(breakpoints[breakpoint]);

  // Set the initial breakpoint on page load.
  if (mql.matches) {
    ga('set', 'dimensionN', breakpoint);
  }

  // Update the breakpoint as the matched media changes, and send an event.
  mql.addListener(function() {
    if (mql.matches) {
      clearTimeout(timeout);
      timeout = setTimeout(function() {
        ga('set', 'dimensionN', breakpoint);
        ga('send', 'event', 'breakpoint', 'change', breakpoint);
      }, 1000);
    }
  });
});

Sinta-se livre para usar este código em seu site, mas não se esqueça de alterar os breakpoints para o que quer que você estiver usando. Se você quiser ver como é a minha implementação (é quase exatamente o mesmo), você pode encontrar o código no GitHub.

Notas de rodapé:

[1] Pode haver situações em que você deseja rastrear mais de uma media query correspondente ao mesmo tempo. Um bom exemplo disso seria rastrear a largura da tela  e a densidade de pixels do dispositivo. Nesses casos, é melhor rastreá-las com duas dimensões distintas. Dentro de uma única dimensão, apenas um valor pode ser aplicado de cada vez.

***

Philip Walton faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://philipwalton.com/articles/measuring-your-sites-responsive-breakpoint-usage/