Html5-boilerplate: Use localStorage para el seguimiento de Google Analytics cuando esté disponible

Creado en 7 oct. 2013  ·  30Comentarios  ·  Fuente: h5bp/html5-boilerplate

TL;RD:

(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','UA-XXXXX-X',{'storage': 'none','clientId':localStorage.getItem('gaClientId')});
ga(function(t){localStorage.setItem('gaClientId',t.get('clientId'));});
ga('send','pageview');

La fuente:
http://stackoverflow.com/questions/4502128/convert-google-analytics-cookies-to-local-session-storage/19207035?noredirect=1#19207035

Documentos de Google Analytics:
https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#disableCookies

Podríamos usar Modernizer.localstorage para verificar el soporte de localStorage y el respaldo a las cookies si no está disponible. Aunque no estoy seguro de si queremos bloquear Modernizr como una dependencia.

¿Por qué?
Porque Google no necesita enviar su cookie a su servidor para cada solicitud individual a su dominio (o al de ellos, para el caso).

new feature

Comentario más útil

Actualizar:

No está en contra de TOS usar localStorage para almacenar el ClientID; ahora cuenta con el respaldo oficial de Google: https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id#using_localstorage_to_store_the_client_id

Nota: si tiene que admitir navegadores (extremadamente) antiguos (como iOS5 y FF4), su fragmento de código de ejemplo puede fallar (consulte: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage. js).

Todos 30 comentarios

Aunque no estoy seguro de si queremos bloquear Modernizr como una dependencia.

¿Tal vez sería mejor simplemente agregarlo a los documentos?

Además, haga ping a @mathiasbynens.

Gracias por optimizar el recorte, David. Como @alrra , creo que estamos bien al agregarlo a los documentos.

El crédito no me pertenece; esto fue traído a mi atención por @elmerbulthuis. Aunque realmente no consideraría esto como una optimización del _snippet_ en sí, per se --- es más una optimización de la web como un todo :-p.

Me pregunto cuántos bytes podrían ahorrarse globalmente si todos adoptaran la solución localStorage .

Obviamente soy un gran admirador de esta solución. El único problema de incluirlo de forma predeterminada en el repetitivo es el que mencionó @davidmurdoch : primero debemos probar las funciones para localStorage . Esto se puede hacer usando Modernizr o agregando una pequeña pieza de código independiente, pero de cualquier manera aumentará ligeramente el tamaño de la página. Por otra parte, ahorrará muchos bytes a largo plazo, ya que no se enviarán cookies en los encabezados de solicitud de ningún recurso en el dominio afectado.

Algo como esto:

(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
(function(){var a=(function(){var c=new Date,b;try{
localStorage.setItem(c,c);b=localStorage.getItem(c)==c;
localStorage.removeItem(c);return b&&localStorage}catch(d){}}());
ga('create','UA-XXXXX-X',a?{storage:'none',clientId:a.gaId}:{});
ga(function(b){a.gaId=b.get('clientId')});ga('send','pageview')}());

(Utiliza la prueba de función localStorage tomada de http://mathiasbynens.be/notes/localstorage-pattern).

Parece funcionar bien después de algunas pruebas rápidas. Crearé un PR después de probar esto más extensamente. (¡Ayuda bienvenida, por supuesto!)

FYI: esto tiene el potencial de ahorrar alrededor de 33 bytes sin procesar (los encabezados/cookies no están comprimidos) por viaje de ida y vuelta para cada solicitud a los dominios afectados.

La solución actual de detección de características en línea de @mathiasbynens es 130 bytes comprimidos* más grande (obviamente, esto será diferente para cada página única, pero nos da una idea aproximada). Entonces, probablemente deberíamos ver si podemos reducir esto un poco más.

Personalmente, me gustaría ver la diferencia comprimida con gzip en 65 bytes y lo intentaré pronto. :-)

_∗usando este deflactor: http://www.vervestudios.co/projects/compression-tests/snippet-deflator_

318 bytes comprimidos en GZIP (nuestra versión actual es de 248 bytes comprimidos en GZIP):

(function(l,e){GoogleAnalyticsObject='ga',(window.ga||(ga=function(l,e){(ga.q=ga.q||[]).push(arguments)})).l=+new Date,l=document.createElement('script'),l.src='//www.google-analytics.com/analytics.js',(e=document.getElementsByTagName('script')[0]).parentNode.insertBefore(l,e);ga('create','UA-XXXXX-X',(function(l,e){try{l=(localStorage[ga.l]=ga.l)==ga.l;localStorage.removeItem(ga.l);return l}catch(l){}}())?{storage:'none',clientId:localStorage.clientId}:{});ga(function(l,e){localStorage.clientId=l.get('clientId')});ga('send','pageview')}())

Esto no se ha probado muy bien, así que aún tendré que hacerlo. Pero es un comienzo.

Y desafortunadamente, la prueba localStorage probablemente esté comprometida en algún navegador en alguna parte, ya que me deshice de las llamadas de setItem y getItem y usé algunos otros "trucos" de golf.

Eso es todo lo que tengo por ahora. :-)

Se me acaba de ocurrir que hemos estado comprimiendo el fragmento en sí, lo cual no tiene sentido. Los resultados de Gzip dependen del resto del documento (es decir, la fuente HTML si está integrada en un documento, o el resto del archivo JavaScript si es parte de uno). ¿Tal vez comparar los tamaños comprimidos con gzip solo del fragmento no es la mejor manera de medir esto?

Tu fragmento se ve bien. ¡Buena captura reutilizando la marca de tiempo ga.l en lugar de generar una nueva!

Y desafortunadamente, la prueba localStorage probablemente esté comprometida en algún navegador en algún lugar, ya que me deshice de las llamadas setItem y getItem y usé algunos otros "trucos" de golf.

Si ese es el caso, sería un factor decisivo en mi humilde opinión.

Podemos reemplazar document.getElementsByTagName('script')[0] con document.scripts[0] cuando la compatibilidad con Firefox <9 ya no sea un problema.

@mathiasbynens GZIPpeando solo el fragmento se aproximará al ahorro de bytes _mínimo_ de la compresión. Así que no es del todo un punto discutible. En casi todos los casos, la relación de compresión del fragmento aumentará a medida que aumente el tamaño de la página.

¡Todavía hay que probar! Agregué las llamadas getItem y setItem y logré reducirlo a 309 bytes:

+function(l,e){(ct=this[GoogleAnalyticsObject='ct']||function(l,e){(ct.q=ct.q||[]).push(arguments)}).l=+new Date,l=document.createElement('script'),l.src='//www.google-analytics.com/analytics.js',(e=document.getElementsByTagName('script')[0]).parentNode.insertBefore(l,e);try{localStorage.setItem(ct.l,ct.l),l=localStorage.getItem(ct.l)-ct.l,localStorage.removeItem(ct.l)}catch(l){};ct('create','UA-XXXXX-X',l?{}:{clientId:localStorage.clientId,storage:'none'}),ct(function(l,e){localStorage.clientId=l.get('clientId')}),ct('send','pageview')}()
  • Ahora estoy usando un IIFE que usa un signo + en lugar de envolver paréntesis.
  • También estoy usando localStorage.clientId en lugar de localStorage.gaId ya que clientId ahorra algunos bytes.
  • Usar this en lugar de window ahorró 1 byte más (en combinación con mover la asignación GoogleAnalyticsObject ).
  • Cambiar ga a ct (ct es más frecuente) ahorró un byte más (probablemente no valga la pena la confusión).
  • Deshacerse de la llamada a la función y reutilizar l para la comprobación de localStorage al asignarlo a 0 en caso de éxito ahorró un montón de bytes.

Nuevamente, esto necesita muchas más pruebas.

@davidmurdoch ¿ Alguna actualización sobre las pruebas? ¿Podemos escribir un flujo de prueba para esto para que otros puedan ayudar a probar?

Lo siento, he sido MIA, me pusieron en un proyecto de alta prioridad de 6 meses y no he podido dedicar mucho tiempo a nada más.

La forma más fácil (y más tonta) de probar esto es simplemente reemplazar su código de análisis con este nuevo código y ver si obtiene alguna fluctuación extraña en los números y las versiones de los navegadores. Lo he hecho yo mismo y no he visto nada que sobresalga. Sin embargo, no tengo muchos oldie visitantes de todos modos.

Otra forma sería cargar este script de análisis experimental en un iframe generado (para no interferir con el fragmento de análisis estable) y llamar a _trackPageview desde allí, bajo una cuenta de GA diferente, por supuesto. Luego solo necesita comparar los datos después de una semana más o menos.

No puedo prometer que pueda trabajar en un fragmento de código para probar esto en el corto plazo; si alguien más quiere apropiarse de estas ideas mientras yo vuelvo a esconderme, por favor adelante. :-)

Acabo de comenzar una prueba para http://drublic.github.io/css-modal/. Obtuve 97,000 páginas vistas los últimos meses, pero se extendieron ampliamente por el navegador.

Los números:

  1. cromo 44,01%
  2. Firefox 34,38%
  3. Internet Explorer 8,86%
  4. Ópera 5,26%
  5. Safari 4,01%
  6. Navegador Android 2.22%

Vamos a esperar y ver. Obtuve las estadísticas "normales" ejecutándose en paralelo.

Aparte de eso, creo que el código necesita algunas actualizaciones más para mejorar la legibilidad (80 caracteres por línea y dónde insertar el identificador).

Volveré a esta prueba en alrededor de una semana.

Llego un poco temprano, pero mis hallazgos son bastante estables en este momento. Desafortunadamente, veo una gran diferencia en el número de visitantes para ambas cuentas.

La implementación predeterminada muestra 2964 visitas únicas del 13 al 17 de marzo.
El almacenamiento local basado muestra 756 visitas únicas para el mismo período de tiempo.

Puede haber tres posibles razones:

  • mi implementación del recorte está dañada
  • la carga del iframe está bloqueada por los navegadores
  • la integración de almacenamiento local de los recortes está rota

Actualmente no veo ningún error en mi código aquí: http://drublic.github.io/css-modal/test-gau-localstorage.html (que es el iframe que se ha integrado en el sitio).

Además, no he experimentado que los navegadores o las páginas bloqueen iframes. ¿Alguien tiene idea de si esto puede pasar?

Lo que me lleva a la solución de que el almacenamiento local GUA cortado tiene errores. No he investigado cuáles podrían ser los problemas.
¿Podemos desarrollar una variante no minimizada para realizar más pruebas y minimizar después de que podamos encontrar una solución que funcione?

También optaría por sacar esto de HTML5BP v5.0 y lanzarlo con 5.1 si encontramos una solución. ¿Qué piensan ustedes?

También optaría por sacar esto de HTML5BP v5.0 y lanzarlo con 5.1

@drublic :+1: (problema agregado al hito v5.1.0 ).

Si sus números están tan apagados, es probable que tenga que proporcionar un ID de cliente predeterminado cuando llame a ga('create', w/ storage:'none' .

https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#disableCookies

Acabo de escribir un blog sobre este problema en mi sitio, aquí: Google Async Analytics usando LocalStorage y configurar una página de prueba aquí: http://davidmurdoch.com/google-async-analytics-using-localstorage-test/.

Por favor, lea, comparta y pruebe.

(nota: si encuentra errores tipográficos o errores en esas páginas, hágamelo saber en twitter @pxcoach .

Oye, siento llegar un poco tarde a la fiesta. Trabajo en el equipo de Google Analytics y quería comentar y ofrecer mi opinión sobre este tema.

En primer lugar, no creo que sea una buena idea que el proyecto H5BP recomiende un fragmento de seguimiento de Google Analytics que sea funcionalmente diferente del recomendado oficialmente. La gente probablemente supondrá que son iguales, y si en realidad no es así, causará confusión. Si la documentación de Google Analytics afirma que GA admite alguna característica y no lo hace porque alguien está usando un fragmento diferente, eso probablemente generará algunos problemas bastante difíciles de depurar (especialmente si H5BP no deja en claro que los fragmentos son diferentes).

Si hay algo que GA podría hacer mejor, nos encantaría evolucionar con las necesidades de la comunidad en lugar de desviarnos de ella. (Por cierto, siéntase libre de hacer ping o enviarme un mensaje de correo electrónico sobre cualquier problema de Github relacionado con GA).

De todos modos, aquí está el problema principal con localStorage y por qué GA no lo ofrece como mecanismo de almacenamiento predeterminado:

localStorage tiene un alcance de location.origin mientras que las cookies pueden tener un alcance de un dominio de nivel superior. El almacenamiento de cookies permite que analytics.js realice el seguimiento de subdominios de forma inmediata, y esto no sería posible con localStorage. Además, si partes de su sitio son HTTP y otras partes son HTTPS, eso también fallaría (y por falla me refiero a que el almacenamiento no se comparte, por lo que perdería la identificación del cliente y GA lo trataría como una sesión separada). ). Si bien es cierto que estas no son preocupaciones para la mayoría de los usuarios de GA, sigo pensando que sería malo ofrecer este fragmento propuesto como un reemplazo directo debido a la pérdida de funciones que acabo de describir.

Dicho esto, según este problema y la publicación de blog de @davidmurdoch , intentaremos priorizar la creación de un mecanismo de almacenamiento local con soporte oficial. Actualmente, el parámetro storage solo admite las opciones cookie y none , pero nos gustaría agregar una tercera opción localStorage para que los usuarios que no necesita subdominio o seguimiento de esquemas cruzados puede optar. No sé cuándo se agregará esto, pero puedo actualizar este problema cuando / si lo es.

¿Parece esto razonable para todos?

@philipwalton ¡ Gracias por el comentario!

¿Parece esto razonable para todos?

CC: @davidmurdoch , @mathiasbynens

Dicho esto, según este problema y la publicación de blog de @davidmurdoch , intentaremos priorizar la creación de un mecanismo de almacenamiento local con soporte oficial.

:+1:

Actualice el problema cuando se agregue. ¡Gracias!

@philipwalton , :+1: ¡Excelentes noticias! Sin embargo, no necesita _intentar_ construirlo, ¡ya lo hicimos! :-p (bromeo, bromeo).

Continuaré y actualizaré mi publicación de blog con esta noticia, y crearé un repositorio de GitHub con el código de seguimiento no oficial localStorage , asegurándome de enfatizar sus deficiencias. ¡Gracias!

:+1: pero también parece que la web del futuro necesita algún tipo de topLevelStorage . Me alegro de que la opción estará disponible. Con eso en mente, y cuando llegue el fragmento, ¿cuál podría ser la preferencia por h5bp?

@jonathantneal , teníamos globalStorage en Firefox, que cruzaba esquemas, puertos y almacenamiento de subdominios. Firefox fue el único que lo implementó y desde entonces se ha marcado como obsoleto. :-(

@davidmurdoch ¡ Muchas gracias por abrir este número y profundizar en él, lo apreciamos sinceramente!

@philipwalton Gracias nuevamente por unirse a la discusión y, como dijo @mathiasbynens , ¡manténganos actualizados!

y cree un repositorio de GitHub con el código de seguimiento localStorage no oficial, asegurándose de enfatizar sus deficiencias.

El repositorio de @davidmurdoch es https://github.com/davidmurdoch/ga-localstorage(aunque aún no está actualizado).

Acabo de publicar el script "Google Analytics usando localStorage" en npm: https://www.npmjs.org/package/ga-localstorage

El repositorio https://github.com/davidmurdoch/ga-localstorage también se actualizó con el código.

Hola, ¿has leído este comentario de SO?

http://stackoverflow.com/questions/4502128/convert-google-analytics-cookies-to-local-session-storage/19207035#comment -44767913

Tendría curiosidad por saber lo que todos ustedes piensan.

@caesarsol Creo que es una muy mala idea. Como describí en mi comentario , las cookies y el almacenamiento local no tienen las mismas restricciones, por lo que cambiarlas por cada secuencia de comandos que se ejecuta en la página es extremadamente arriesgado.

hola @philipwalton , gracias por la respuesta, pero tal vez me expliqué mal, me refería a este comentario del usuario SO _smhmic_:

¡Esto podría violar los TOS de GA! Aquí hay una cita de segunda mano de un miembro del equipo de GA, tomada de este artículo: "Usar mecanismos de administración de estado HTTP" (léase: localStorage) "para propagar el estado de las cookies es una elusión de nuestras garantías de privacidad. Hacerlo viola los Términos de servicio de Google Analytics ". Mi interpretación de esto es que GA emplea cookies y no localStorage porque más usuarios están familiarizados con el concepto de cookies y cómo borrarlas; por lo tanto, el uso de cookies por parte de GA es una función de privacidad. - smhmic

El uso de mecanismos de gestión de estado HTTP" (léase: almacenamiento local) para propagar el estado de las cookies es una elusión de nuestras garantías de privacidad. Hacerlo viola los Términos de servicio de Google Analytics

Hmmm, no creo que esto sea cierto. Hay funciones de exclusión voluntaria que proporciona GA (por ejemplo, extensiones de Chrome) que no dependen de que el implementador use cookies. Creo que el punto de esta sección de los TOS es que no se puede crear un mecanismo por el cual alguien que esté usando una extensión oficial de "no rastrear" _todavía_ sea rastreado.

Puedo investigarlo más a fondo y actualizaré este hilo si mis suposiciones resultan ser falsas.

Actualizar:

No está en contra de TOS usar localStorage para almacenar el ClientID; ahora cuenta con el respaldo oficial de Google: https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id#using_localstorage_to_store_the_client_id

Nota: si tiene que admitir navegadores (extremadamente) antiguos (como iOS5 y FF4), su fragmento de código de ejemplo puede fallar (consulte: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage. js).

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

alrra picture alrra  ·  18Comentarios

coliff picture coliff  ·  12Comentarios

coliff picture coliff  ·  10Comentarios

neilcreagh picture neilcreagh  ·  28Comentarios

coliff picture coliff  ·  14Comentarios