Sun. Oct 13th, 2024

Seguimiento de usuarios que están desconectados en Google Analytics


El aumento constante del uso de dispositivos móviles en los últimos años ha introducido algunos nuevos desafíos para la analítica internet. No se trata solo de desajustes en el modelo de seguimiento (el concepto de sesiones es aún más absurdo para las aplicaciones que para la navegación en el escritorio), pero se trata de algo más basic, más básico. Piénselo: si un visitante accede al sitio internet usando un dispositivo móvil, existe una probabilidad significativa de que pierda la conexión a Web y se desconecte involuntariamente.

En realidad, les basta con atravesar un área con poca cobertura: si las solicitudes HTTP enviadas por el navegador no se completan a tiempo, se agota el tiempo de espera y se pierden los resultados.

Para Google Analítico Las visitas a la página no son tan importantes, porque si el usuario ve la página internet, es muy possible que la primera visita a la página se haya completado. Sin embargo, ¿qué sucede con todas las demás interacciones que queremos rastrear y para las que el usuario no tiene conexión a Web? Así es, perderemos estas interacciones, ya que el navegador descarta las solicitudes y nunca las recupera, incluso cuando el usuario recupera su conexión.

En este artículo, el brillante David Vallejo y ofreceré una solución para recuperar estos resultados que el navegador inicialmente dejó caer debido a que la conexión a Web no funciona. Bien, ¿a quién engaño? Todo esto es obra de David. En este momento, solo soy un editor glorificado.

De todos modos, planteémoslo de esta manera: el visitante está viendo nuestra página de contacto y tenemos un evento programado para cuando haga clic en nuestra información de contacto por correo electrónico. Sin embargo, el visitante también está en el metro y, en el momento en que hace clic en el correo electrónico, ingresa a un túnel. ¡Oh, no! Pierde su conexión a Web (malditos subterráneos sin WiFi) y perdemos nuestro seguimiento de conversiones very important.

Esa es la premisa. Aquí está la ejecución.

En este artículo abordaremos una serie de conceptos bastante técnicos, pero intentaremos enmarcarlos de forma que tengan sentido en el panorama basic.

  1. Analítica common API de tareas

  2. El navegador API de almacenamiento

  3. Envío de visitas de Google Analytics con retraso (el &qt parámetro)

  4. Envío de solicitudes POST y HEAD personalizadas (protocolo HTTP)

  5. Procesamiento por lotes Éxitos de Common Analytics

Todos estos conceptos son muy útiles si quieres saber más sobre los mecanismos que utiliza el navegador internet para compilar y enviar solicitudes a Common Analytics.

¡Vamos!


incógnita


El boletín informativo de Simmer

Suscríbete a la Boletín informativo de Simmer ¡Para recibir las últimas noticias y contenidos de Simo Ahava en tu bandeja de entrada de correo electrónico!

1. API de tareas de Common Analytics

Cada vez que un ship El comando se envía a la ga() método international, una serie de tareas La biblioteca analytics.js ejecuta las tareas en secuencia. Estas tareas realizan varias cosas, como construir la carga útil, validarla, muestrear las solicitudes y, finalmente, enviar las solicitudes al punto de conexión de Common Analytics.

Lo bueno de estas tareas es que podemos interceptarlas y modificarlas utilizando la API proporcionada por analytics.js.

Puede encontrar una lista de todas las tareas disponibles en la API aquíSin embargo, en este artículo nos centraremos en una tarea muy especial y muy significativa: customTaskEs una nueva tarea introducida muy recientemente (aquí hay una Guía de Simo).

Esta tarea hace honor a su nombre: es totalmente personalizable. Se ejecuta primero en la cola de tareas, por lo que puede usarla para configurar el objeto de seguimiento o incluso para configurar otras tareas para personalizarlas.

En esta guía, utilizaremos customTask Para modificar el sendHitTaskDe esta manera podemos comprobar si el usuario tiene conexión a Web cuando sendHitTask se ejecuta y podemos hacer varias cosas si el usuario ha perdido la conexión. Usamos customTask en lugar de acceder directamente sendHitTask simplemente porque de esta manera es mucho más Administrador de etiquetas de Google-amigable.

En resumen, este es el proceso:

customTask modifica sendHitTask con OUR CODE antes El golpe se envía.

Para detectar si el usuario tiene conexión a Web, podríamos simplemente sondear nuestro propio servidor internet. Sin embargo, no sería una buena prueba de fuego, ya que podrían ser solo los servidores de Google los que no responden. Por eso, sondearemos el punto closing de Google para verificar si el usuario tiene la conectividad necesaria para el seguimiento de Google Analytics.

2. El rastreador sin conexión

La solución es que con cada solicitud a Common Analytics, enviaremos una solicitud HTTP HEAD al punto de conexión de Common Analytics. Si el punto de conexión no responde, podemos inferir que el usuario no tiene conectividad para comunicarse con Google Analytics, por lo que almacenaremos la solicitud en el almacenamiento del navegador hasta que se restablezca la cobertura de Web.

Nosotros lo usaremos localStorage para la cola, pero tendremos que hacer un poco de trampa. localStorage En sí mismo no introduce ninguna estructura ni un modelo de datos más profundo: solo procesa pares clave-valor. Por lo tanto, para brindarnos cierta flexibilidad adicional, utilizaremos el Bloqueador Capa de base de datos de código abierto. Es un marco easy y eficiente, y tiene una compatibilidad bastante sólida con los navegadores.

Esta solución recoge la carga útil de Common Analytics desde sendHitTasky si no hay conexión a Web, este hit se almacena en localStorage con la marca de tiempo de la solicitud. De esta forma, cuando más tarde logremos enviar el hit almacenado, podremos enviarlo en su marca de tiempo authentic a Common Analytics.

2.1 El parámetro &qt

El &qt Protocolo de medición significa tiempo de esperaBásicamente, puedes establecer un número en milisegundos en ese parámetro y el hit se enviará con una marca de tiempo que indica esa cantidad de milisegundos en el pasado. Por ejemplo, si sé que el hit que quiero enviar ocurrió hace 45 minutos, puedo establecer el parámetro en:

&qt=2700000

Hay una pequeña peculiaridad extraña que debes conocer &qtLa última vez que se puede enviar el hit desplazado es a las 03:59:59 del día siguiente (en la zona horaria de la vista de Google Analytics a la que se envía el hit). Por lo tanto, el valor máximo para &qt son 27 horas, 59 minutos y 59 segundos (en milisegundos), si el impacto se produce exactamente a medianoche y luego lo envías a la mañana siguiente, justo antes de las 4 a. m.

Sí, puede que sea difícil de entender, así que vamos con la recomendación oficial: Evite enviar visitas con más de 4 horas de antigüedadya que no hay garantía de que se envíen.

3. La solicitud HTTP HEAD

Entonces, ¿qué es esto? Solicitud HEAD ¿Y por qué lo usamos? Bueno, es idéntico a GET, excepto que solo devuelve los encabezados HTTP (y los metadatos asociados), nunca ningún contenido.

Por lo tanto, es un excelente método para usar si solo queremos probar un punto closing y no entrar en el costoso proceso de recuperar datos de él.

Como solo nos interesa saber si el endpoint de Common Analytics responde, la solicitud HTTP HEAD es perfecta para este propósito. Además, vea qué tan eficiente es en comparación con POST y GET:

4. El código JavaScript

El código consta de tres partes. La primera es la biblioteca para ampliar la base de datos: BloqueadorA continuación tenemos el customTask ejecución y, finalmente, encadenaremos el HTTP HEAD y las solicitudes por lotes para que todo funcione.

4.1. Descarga de Lockr

Para comenzar, siga adelante y carga Bloqueador en su sitio de la forma que desee. Si está utilizando Google Tag Supervisor, le recomendamos cargar el siguiente código en un Etiqueta HTML personalizada que dispara en Todas las páginas Con el mayor nivel posible Prioridad de etiquetasAlternativamente, si acepta cierta sobrecarga y redundancia, puede simplemente agregar la biblioteca en la parte superior de la variable JavaScript personalizada, como en el ejemplo del próximo capítulo.

Aquí está el código JavaScript minimizado: el navegador debe ejecutarlo antes de que se ejecute la solución de seguimiento sin conexión:

!operate(e,t){"undefined"!=typeof exports?"undefined"!=typeof module&&module.exports&&(exports=module.exports=t(e,exports)):"operate"==typeof outline&&outline.amd?outline(("exports"),operate(r){e.Lockr=t(e,r)}):e.Lockr=t(e,{})}(this,operate(e,t){"use strict";return Array.prototype.indexOf||(Array.prototype.indexOf=operate(e)0;for((r=r<0?Math.ceil(r):Math.ground(r))<0&&(r+=t);rif(r in this&&this(r)===e)return r;return-1),t.prefix="",t._getPrefixedKey=operate(e,t){return(t=t||{}).noPrefix?e:this.prefix+e},t.set=operate(e,t,r){var o=this._getPrefixedKey(e,r);attempt{localStorage.setItem(o,JSON.stringify({information:t}))}catch(r){console&&console.warn("Lockr did not efficiently save the '{"+e+": "+t+"}' pair, as a result of the localStorage is full.")}},t.get=operate(e,t,r){var o,n=this._getPrefixedKey(e,r);attempt{o=JSON.parse(localStorage.getItem(n))}catch(e){o=localStorage(n)?{information:localStorage.getItem(n)}:null}return o?"object"==typeof o&&void 0!==o.information?o.information:void 0:t},t.sadd=operate(e,r,o){var n,a=this._getPrefixedKey(e,o),i=t.smembers(e);if(i.indexOf(r)>-1)return null;attempt{i.push(r),n=JSON.stringify({information:i}),localStorage.setItem(a,n)}catch

Después de este vómito de código, ¡estamos listos para saltar a lo profundo con un poco de seguimiento de visitas fuera de línea!

4.2. Rastreador de visitas sin conexión para Common Analytics en la página

El siguiente JavaScript se ejecuta con el valor predeterminado Rastreador de Common Analyticsy por lo tanto, cualquier hit enviado con el ga('ship', '...'); se incluirán en el proceso.

Para que todo funcione, debes configurar tu código en el siguiente orden:

<head>
  ...
  <script>
    // Put the Lockr code right here first
  script>
  <script>
    var _offlineTracker = operate(customTaskModel) {
      // _offlineTracker (see beneath) right here
    };
  script>
  <script>
    // Common Analytics snippet right here
    ga('create', 'UA-12345-1');
    // Add the next line AFTER the 'create' command and BEFORE the primary 'ship' command
    ga('set', 'customTask', _offlineTracker);
    ga('ship', 'pageview');
  script>
  ...
head>

Y aquí está el código para el _offlineTracker función de devolución de llamada.

var _offlineTracker = operate(customTaskModel) {

  Lockr.prefix = 'ga_';
  // Seize the unique sentHitTask Perform from the primary tracker. to saved the unique hit sending operate.
  var originalSendHitTask = customTaskModel.get('sendHitTask');
  customTaskModel.set('sendHitTask', operate(mannequin) {
    // Let's ship the unique hit utilizing the native performance
    originalSendHitTask(mannequin);
    // Seize the hit Payload
    var payload_lz = mannequin.get('hitPayload');
    // Test if GA Endpoint is Prepared
    var http = new XMLHttpRequest();
    http.open('HEAD', 'https://www.google-analytics.com/gather');
    http.onreadystatechange = operate() {
      // Google Analytics endpoint isn't reachable, let's save the hit                
      if (this.readyState === this.DONE && this.standing !== 200) {
        Lockr.sadd('hits', payload_lz + "&qt=" + (new Date() * 1));
      } else {
        // Google Analytics endpoint is on the market, let's test if there are any unsent hits
        if (Lockr.smembers("hits").size > 0) {                        
          // Course of hits in queue
          var current_ts = new Date() * 1 / 1000;
          var hits = Lockr.smembers("hits");

          // ./batch endpoint solely permits 20 hits per batch, let's chunk the hits array. 
          var chunk_size = 20;
          var chunked_hits = Lockr.smembers("hits").map(operate(e, i) {
            return i % chunk_size === 0 ? hits.slice(i, i + chunk_size) : null;
          }).filter(operate(e) {
            return e;
          });
          // Let's loop via the chunks array and ship the hits to GA
          for (var i = 0; i < chunked_hits.size; i++) {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'https://www.google-analytics.com/batch', true);
            // Construct the Batch Payload and Maintain calculating the Queue Time 
            xhr.ship(chunked_hits(i).map(operate(x) {
              if (x.indexOf("&qt=") > -1) {
                return x.substitute(/qt=((^&)*)/, "qt=" + Math.spherical(current_ts - x.match(/qt=((^&)*)/)(1) / 1000) * 1000);
              } else return x;
            }).be part of("n"));
          }
          //Hits despatched, flush the Storage
          Lockr.flush();
        }
      }
    };
    http.ship();
  });
};

Una vez que crees esto _offlineTracker e invocarlo en el ga('set', 'customTask', _offlineTracker) Comando: cada hit que utilice este rastreador se almacenará en la cola si no hay conexión a Web. Una vez que se envía un hit con una conexión estable, también se envían todos los hits en la cola.

4.3. Rastreador de visitas sin conexión para Google Tag Supervisor

Con Google Tag Supervisor, puedes arreglártelas con una única variable de JavaScript personalizada. Esta variable se puede configurar para que también incluya el código de Lockr, por lo que es completamente autónoma. Dale a la variable un nombre descriptivo, por ejemplo {{JS – Rastreador de visitas sin conexión de customTask}} y poner el siguiente código dentro:

operate() {
  return operate(customTaskModel) {
    // Load Lockr if it hasn't already been loaded
    if (!window.Lockr) {
      !operate(e,t){"undefined"!=typeof exports?"undefined"!=typeof module&&module.exports&&(exports=module.exports=t(e,exports)):"operate"==typeof outline&&outline.amd?outline(("exports"),operate(r){e.Lockr=t(e,r)}):e.Lockr=t(e,{})}(this,operate(e,t){"use strict";return Array.prototype.indexOf||(Array.prototype.indexOf=operate(e)0;for((r=r<0?Math.ceil(r):Math.ground(r))<0&&(r+=t);rif(r in this&&this(r)===e)return r;return-1),t.prefix="",t._getPrefixedKey=operate(e,t){return(t=t||{}).noPrefix?e:this.prefix+e},t.set=operate(e,t,r){var o=this._getPrefixedKey(e,r);attempt{localStorage.setItem(o,JSON.stringify({information:t}))}catch(r){console&&console.warn("Lockr did not efficiently save the '{"+e+": "+t+"}' pair, as a result of the localStorage is full.")}},t.get=operate(e,t,r){var o,n=this._getPrefixedKey(e,r);attempt{o=JSON.parse(localStorage.getItem(n))}catch(e){o=localStorage(n)?{information:localStorage.getItem(n)}:null}return o?"object"==typeof o&&void 0!==o.information?o.information:void 0:t},t.sadd=operate(e,r,o){var n,a=this._getPrefixedKey(e,o),i=t.smembers(e);if(i.indexOf(r)>-1)return null;attempt{i.push(r),n=JSON.stringify({information:i}),localStorage.setItem(a,n)}catch
    }
    Lockr.prefix = 'ga_';
    // Seize the unique sentHitTask Perform from the primary tracker. to saved the unique hit sending operate.
    var originalSendHitTask = customTaskModel.get('sendHitTask');
    customTaskModel.set('sendHitTask', operate(mannequin) {
      // Let's ship the unique hit utilizing the native performance
      originalSendHitTask(mannequin);
      // Seize the hit Payload
      var payload_lz = mannequin.get('hitPayload');
      // Test if GA Endpoint is Prepared
      var http = new XMLHttpRequest();
      http.open('HEAD', 'https://www.google-analytics.com/gather');
      http.onreadystatechange = operate() {
        // Google Analytics endpoint isn't reachable, let's save the hit                
        if (this.readyState === this.DONE && this.standing !== 200) {
          Lockr.sadd('hits', payload_lz + "&qt=" + (new Date() * 1));
        } else {
          // Google Analytics endpoint is on the market, let's test if there are any unsent hits
          if (Lockr.smembers("hits").size > 0) {                        
            // Course of hits in queue
            var current_ts = new Date() * 1 / 1000;
            var hits = Lockr.smembers("hits");

            // ./batch endpoint solely permits 20 hits per batch, let's chunk the hits array. 
            var chunk_size = 20;
            var chunked_hits = Lockr.smembers("hits").map(operate(e, i) {
              return i % chunk_size === 0 ? hits.slice(i, i + chunk_size) : null;
            }).filter(operate(e) {
              return e;
            });
            // Let's loop via the chunks array and ship the hits to GA
            for (var i = 0; i < chunked_hits.size; i++) {
              var xhr = new XMLHttpRequest();
              xhr.open('POST', 'https://www.google-analytics.com/batch', true);
              // Construct the Batch Payload and Maintain calculating the Queue Time 
              xhr.ship(chunked_hits(i).map(operate(x) {
                if (x.indexOf("&qt=") > -1) {
                  return x.substitute(/qt=((^&)*)/, "qt=" + Math.spherical(current_ts - x.match(/qt=((^&)*)/)(1) / 1000) * 1000);
                } else return x;
              }).be part of("n"));
            }
            //Hits despatched, flush the Storage
            Lockr.flush();
          }
        }
      };
      http.ship();
    });
  };
}

Añade este código a Todas sus etiquetas de Common Analytics desplazándose hasta Más configuraciones -> Campos a configurarAquí se agrega un nuevo campo con:

Nombre del campo: Tarea personalizada
Valor: {{JS – Rastreador de visitas sin conexión de customTask}}

Una vez que hayas hecho esto, entonces todas tus etiquetas con esto Tarea personalizada La configuración está protegida contra mala conectividad y, cada vez que se restablece la conexión, se procesa la cola de lotes.

4.4. Acerca del procesamiento por lotes

Common Analytics le permite enviar visitas a su punto closing en lotesEsto lo utilizan principalmente los SDK de iOS y Android. El objetivo principal de utilizar el punto closing por lotes (/batch) consiste en enviar la menor cantidad posible de solicitudes HTTP. En este caso, la agrupación significa que podemos enviar varias cargas útiles de Common Analytics en una única solicitud HTTP.

El procesamiento por lotes tiene algunas limitaciones que debemos tener en cuenta:

  • Se puede especificar un máximo de 20 resultados por solicitud.

  • El tamaño combinado de todas las cargas útiles impactadas no puede ser mayor a 16 Ok bytes.

  • Ninguna carga útil de un solo impacto puede ser mayor a 8K bytes.

  • La solicitud debe realizarse mediante POST

Para nuestra solución, cada vez que la cantidad de hits almacenados es mayor que 1, enviamos las cargas útiles mediante el punto closing de procesamiento por lotes. En caso de que haya demasiados hits almacenados en la cola, los dividimos en fragmentos para que se envíen varias solicitudes por lotes en sucesión hasta que se procese toda la cola.

5. Mejoras

Tenga en cuenta que esta publicación precise tiene como objetivo mostrar cómo realizar un seguimiento de las visitas que pueden ocurrir mientras el usuario está desconectado (debido a una falla de conectividad). Al mismo tiempo, hemos aprovechado la oportunidad para mostrar algunas funcionalidades interesantes y relativamente poco conocidas de la API de JavaScript de Google Analytics.

Una mejora sólida sería omitir el originalSendTask parte, y simplemente sobrescribir el sendHitTask tarea por completo. De esta manera, puede omitir la solicitud HTTP HEAD, ya que solo puede verificar si el acceso inicial a Google Analytics se envió correctamente.

Lo único que debes tener en cuenta si quieres sobrescribir el sendHitTask es que necesitarás replicar el transport lógica para la solicitud. La biblioteca analytics.js admite tres formas diferentes de enviar las solicitudes:

  1. 'picture' – tamaño máximo de carga útil de 2K enviado con una solicitud GET a un punto closing de píxel

  2. 'xhr' – tamaño máximo de carga útil de 8K enviado como una solicitud HTTP POST

  3. 'beacon' – Solicitud POST que utiliza el navigator.sendBeacon() para asegurarse de que sus solicitudes se envíen incluso si el usuario ya ha abandonado la página

Por lo tanto, necesitarás replicar esta lógica en tu aplicación personalizada. sendHitTask método. No es algo que sea fácil de hacer, pero un desarrollador capaz debería poder hacerlo, especialmente una vez que se conocen las restricciones (ver párrafo anterior).

Otra cosa que quizás quieras hacer es agregar un Dimensión personalizada a todas las cargas útiles que se almacenan en la cola. Esta dimensión personalizada podría tener un nombre comparable a Golpe fuera de líneay debes establecer el valor en true Si el hit se envió desde la cola sin conexión. De esta manera, puede controlar cuántos hits en sus datos se cancelaron inicialmente debido a una mala conectividad a Web.

6. Resumen

Me alegra mucho que David sea la estrella invitada en este weblog. ¡Hacía mucho tiempo que no lo veíamos! Esta solución es genial por dos motivos. En primer lugar, es muy útil, especialmente si tu sitio está dirigido a visitantes móviles. En segundo lugar, muestra una serie de características del navegador internet y de la biblioteca analytics.js que también se pueden ampliar a otros fines.

La API de tareas es realmente interesante, ya que permite manipular las cargas útiles enviadas por el sitio internet. Y con la introducción de Tarea personalizadaPor fin tenemos una forma muy práctica de acceder a las tareas con Google Tag Supervisor.

Tenga en cuenta que si tiene una aplicación internet con capacidades sin conexión y está utilizando trabajadores de servicio para administrar esta funcionalidad, Google ha lanzado una biblioteca útil para emplear trabajadores de servicios para hacer exactamente lo mismo que estamos haciendo en este artículo.

¡Esperamos que hayas disfrutado de esta solución! Cuéntanoslo en los comentarios.

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *