Analytics

Test de délai d’extrait de code anti-scintillement de Google Optimize

Récemment, j’ai publié un article sur la façon de mettre en place un essai d’impact pour « l’effet de scintillement » omniprésent dans les outils de test A/B côté client. Assurez-vous de consulter cet article en premier pour obtenir un contexte sur ce dont nous allons parler ici.

Optimiser le test d'extrait de code anti-scintillement

Dans ce court suivi, je vais vous montrer comment mesurer le temps moyen pendant lequel l’extrait anti-scintillement retarde la visibilité de la page, si vous choisissez de déployer l’extrait. La méthodologie est très similaire.

Si vous vous en souvenez, l’extrait de code anti-scintillement se cache la page entière en attendant le chargement du conteneur Optimize. Nous allons donc mesurer le temps qu’il a fallu pour que la page s’affiche. La visibilité est restaurée si le conteneur Optimize se charge correctement ou si le chargement se termine par un délai d’attente (4 secondes par défaut).

Le test ci-dessous est exécuté en répartissant 50 % du trafic vers l’extrait Optimize asynchrone et 50 % du trafic vers la balise Google Tag Manager Optimize.

Nous utilisons Google Analytics : App + Web avec sa merveilleuse exportation BigQuery pour l’analyse. Nous utiliserons Google Tag Manager pour collecter et envoyer les données.

Modifier le modèle de page

Vous devez modifier le modèle de pages. L’extrait anti-scintillement devoir être ajouté directement au modèle de page, et nous devons également écrire la logique qui détermine si l’utilisateur doit voir l’extrait Optimize ou si Optimize doit être chargé via Google Tag Manager.

Au tout Haut du <head> sur vos pages de test, ajoutez le bloc HTML suivant :

<!-- The style declaration for the anti-flicker snippet --> <style>.async-hide { opacity: 0 !important} </style>  <script>   (function() {     // Modify the optimizeId to match your Optimize container ID, gtmId     // to match your GTM container ID, and dataLayerName to match the name     // of the dataLayer array on your site.     var optimizeId = 'GTM-NGM64B',         gtmId = 'GTM-PZ7GMV9',         dataLayerName = 'dataLayer',         hideObj = {},         hideGTMId = Math.random() < 0.5 ? optimizeId : gtmId;          hideObj[hideGTMId] = true;          // Helper to handle the dataLayer.push()     var dPush = function(status) {       window[dataLayerName].push({         event: 'optimize_anti_flicker_test',         milestones: {           antiFlickerStart: window[dataLayerName].hide.start,           antiFlickerEnd: new Date().getTime(),           testStatus: status         }       });     };      // MODIFIED anti-flicker snippet     (function(a,s,y,n,c,h,i,d,e) {       s.className + = ' ' + y;       h.start = 1 * new Date;       h.end = i = function(){         clearTimeout         s.className = s.className.replace(RegExp(' ?' + y), '')       };       (a[n] = a[n] || []).hide = h;       var t = setTimeout(function() {         dPush('timeout');         i();         h.end = null;       }, c);       h.timeout = c;     })(window, document.documentElement, 'async-hide', dataLayerName, 4000, hideObj);      // Determine where to load Optimize from (inline vs. GTM)     if (hideGTMId === optimizeId) {       var el = document.createElement('script');       el.src = 'https://www.googleoptimize.com/optimize.js?id=' + optimizeId;       el.addEventListener('error', function() {         dPush('optimizeSnippetError');         window[dataLayerName].hide.end && window[dataLayerName].hide.end();       });       document.head.appendChild(el);     } else {       window[dataLayerName].push({         gtmOptimize: true       });     }          // Configure the Optimize callback     function gtag() {dataLayer.push(arguments)};     gtag('event', 'optimize.callback', {       callback: function() {         dPush(hideGTMId === optimizeId ? 'optimizeSnippet' : 'gtmTag');       }     });   })(); </script>

Vous ne devez ajouter cet extrait que sur les pages qui exécutent réellement le test, afin de vous assurer de ne pas collecter accidentellement des mesures à partir de pages qui n’exécutent pas réellement Optimize.

Dans le premier bloc de variables, assurez-vous de mettre à jour optimizeId, gtmIdet dataLayerName pour refléter votre ID Optimize, l’ID de conteneur Google Tag Manager et le nom du dataLayer tableau, respectivement.

var hideGTMId = Math.random() < 0.5 ? optimizeId : gtmId; choisit au hasard (50 % de chances) de charger Optimize à l’aide de l’extrait de code asynchrone ou via une balise Google Tag Manager.

Les extrait anti-scintillement est modifié dans cette version. Le principal changement est que si le délai d’expiration se produit (par défaut 4000 millisecondes après le masquage de la page), un dataLayer.push() est appelée avec cette information. Pour cette raison, une autre modification de l’extrait consiste à arrêter le compteur de timeout dans le cas où la page n’est pas masquée (pour éviter que le timeout ne soit signalé par erreur à dataLayer):

h.end = i = function() {   clearTimeout   ... } var t = setTimeout(function() {   dPush('timeout');   ... }, c); 

Le bloc suivant vérifie si Optimize doit être chargé via l’extrait de code ou via GTM.

// Determine where to load Optimize from (inline vs. GTM) if (hideGTMId === optimizeId) {   var el = document.createElement('script');   el.src = 'https://www.googleoptimize.com/optimize.js?id=' + optimizeId;   el.addEventListener('error', function() {   dPush('optimizeSnippetError');     window[dataLayerName].hide.end && window[dataLayerName].hide.end();   });   document.head.appendChild(el); } else {   window[dataLayerName].push({     gtmOptimize: true   }); } 

Si l’extrait de code en ligne remporte le tirage au sort, l’élément Optimize est ajouté à la page avec un error écouteur qui affiche la page en cas d’erreur lors du chargement d’Optimize (par exemple, l’utilisateur bloque le chargement du script).

Si Optimize est chargé via Google Tag Manager, la clé gtmOptimize est poussé à dataLayer avec la valeur true. Ceci est ensuite utilisé comme condition de déclenchement pour la balise Optimize.

Dès que le conteneur Optimize ou Google Tag Manager se charge, ou que l’extrait de code anti-scintillement arrive à expiration, ou qu’il y a une erreur lors du chargement d’Optimize, un dataLayer.push() se produit avec le contenu suivant :

{   event: 'optimize_anti_flicker_test',   milestones: {     antiFlickerStart: window[dataLayerName].hide.start,     antiFlickerEnd: new Date().getTime(),     testStatus: status   } } 

Ici, status fait partie de gtmTag (si Optimize est chargé via Google Tag Manager), optimizeSnippet (si chargé via Optimize), timeout (si le timeout est atteint), ou optimizeSnippetError (si l’extrait Optimize a rencontré une erreur).

Une chose à noter est que cette configuration ne ne pas testez si Google Tag Manager est bloqué. C’est quelque chose que vous voudrez peut-être également tester, si vous voulez avoir une idée encore plus complète de ce qui se passe avec vos implémentations d’expérience.

Configuration de Google Gestionnaire de balises

Dans Google Tag Manager, nous devrons créer un Balise Application + Web (parce que nous voulons refaire l’analyse dans BigQuery). Nous aurons également besoin d’un Déclencheur d’événement personnalisé et certaines Variables de la couche de données.

Le déclencheur

Voici à quoi ressemble le déclencheur d’événement personnalisé.

Déclencheur d'événement personnalisé

Ce déclencheur se déclenchera chaque fois que le dataLayer.push() avec les données de test d’extrait de code sont exécutées sur la page. Il existe également une condition pour ne déclencher cette balise que sur la page d’accueil, que vous pouvez et devez modifier/supprimer si vous effectuez également des expériences ailleurs !.

Les variables

Vous allez avoir besoin quatre dataLayer variables.

Nom de variable Valeur du champ “Nom de la variable de la couche de données” But
DLV – jalons.testStatus milestones.testStatus Un des gtmTag, optimizeSnippet, timeoutou alors optimizeSnippetError.
DLV – jalons.antiFlickerStart milestones.antiFlickerStart Horodatage du début du masquage de la page.
DLV – jalons.antiFlickerEnd milestones.antiFlickerEnd Horodatage de la fin du masquage de la page.
DLV – gtmOptimize gtmOptimize Est true si Optimize doit être chargé dans une balise GTM.

Voici à quoi ressemblerait une variable, selon les spécifications du tableau ci-dessus :

Variable de couche de données

Les balises

Tout d’abord, vous devrez créer le Balise d’événement Application + Web. Assurez-vous également d’avoir une balise de base !

Balise d'événement anti-scintillement Application + Web

La balise est configurée pour se déclencher avec le déclencheur d’événement personnalisé que nous avons créé ci-dessus, et elle envoie les valeurs des trois milestones variables à App + Web en tant que paramètres personnalisés. N’hésitez pas à modifier les clés et les noms d’événements comme vous le souhaitez.

Ensuite, nous devons déclencher la balise Google Optimize conditionnellementselon si le gtmOptimize la clé est dans dataLayer avec la valeur true.

Étant donné qu’Optimize doit s’exécuter dans une séquence de balises, c’est en fait assez compliqué à faire. En plus de la balise Google Optimize elle-même, vous avez besoin d’un nouveau Affichage de la page d’analyse universelle balise qui ne se déclenche que lorsque gtmOptimize est trueet vous devez bloquer votre balise de vue de page standard dans cette circonstance aussi.

Optimiser la balise

Ne vous inquiétez pas du paramètre Séquencement des balises, vous le configurez dans la nouvelle balise Page View que vous devrez également créer :

Nouvelle balise de vue de page

Prenez note du nouveau déclencheur : “Toutes les pages – Anti-scintillement” est un Affichage des pages déclencheur avec une seule condition : {{DLV - gtmOptimize}} equals true.

Enfin, assurez-vous de bloc ton ordinaire Balise de vue de page pour éviter le double comptage sur les pages où la vue de page spécifique à Optimize s’est déjà déclenchée :

Déclencheur de vue de page

Le déclencheur de blocage est un déclencheur d’événement personnalisé qui bloque tout événement si gtmOptimize est true:

Bloquer si optimiser

Testez la configuration

Une fois que vous avez tout configuré, essayez de charger la page avec la modification du modèle de page en mode Aperçu. Assurez-vous de voir une demande à App + Web avec vos paramètres personnalisés en place.

Le hit App + Web fonctionne

Si cela ne fonctionne pas, vérifiez la console du navigateur pour les erreurs. Assurez-vous également que le conteneur Optimize se charge réellement et qu’un test est en cours d’exécution sur la page sur laquelle vous testez !

Creusez en profondeur avec BigQuery

Une fois que les données commencent à affluer dans BigQuery, vous devriez trouver vos événements avec une requête comme celle-ci :

SELECT   * FROM    `project.dataset.events_202006*` WHERE   event_name = 'optimize_anti_flicker_snippet_test'

Nous chargeons simplement tous les hits avec le optimize_anti_flicker_snippet_test données pour obtenir un aperçu de ce à quoi ressemblent ces hits.

Événements anti-scintillement

Pour obtenir un décompte des différents types de test, vous pouvez exécuter une requête comme celle-ci :

SELECT   (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'test_status') as test_status,   COUNT(*) as count FROM   `project.dataset.events_202006*` WHERE   event_name = 'optimize_anti_flicker_snippet_test' GROUP BY 1 ORDER BY 2 DESC

Cette requête extrait la valeur de test_status à partir des événements et effectue un décompte global de chaque statut. Voici à quoi ressemblerait le résultat final :

L'état du test compte

Enfin, pour obtenir des moyennes en place, vous pouvez modifier la requête pour qu’elle ressemble à ceci :

WITH milestones AS (   SELECT      (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'test_status') as test_status,     (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'anti_flicker_start') as anti_flicker_start,     (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'anti_flicker_end') as anti_flicker_end   FROM      `project.dataset.events_202006*`   WHERE     event_name = 'optimize_anti_flicker_snippet_test' ) SELECT    test_status,   COUNT(*) as count,   ROUND(AVG(anti_flicker_end - anti_flicker_start), 2) as average_delay_in_ms, FROM    milestones WHERE anti_flicker_end - anti_flicker_start < 5000 GROUP BY 1 ORDER BY 3 DESC

Les WITH...AS block crée une table source avec uniquement l’état du test et les heures de début et de fin du scintillement en place. Nous pouvons ensuite interroger cette expression de table commune (CTE) pour obtenir correctement nos décomptes et nos moyennes.

Comme vous pouvez le voir, j’ai un WHERE clause en place où je m’assure que le delta ne dépasse pas 5000 millisecondes. En effet, le test entraînait parfois des deltas anormalement élevés, probablement en raison de l’utilisation du conteneur Optimize extrêmement lent à charger, et produisant ainsi l’heure de fin beaucoup plus tard que le délai d’attente.

Avec le WHERE clause, nous ignorons ces deltas anormaux. Nous pouvons le faire car nous ne sommes intéressés que par la durée de la page cachéet si la page est masquée plus de 4 secondes (et change), elle est automatiquement révélée par l’extrait de code anti-clignotement lui-même.

Quoi qu’il en soit, cette requête produit le résultat suivant pour mon jeu de données :

Test d'extrait de code anti-scintillement

Le temps moyen de masquage de la page si l’extrait de code atteint son délai d’expiration est de 3,8 secondes. C’est un peu bizarre car le délai d’attente ne devrait pas arriver avant 4000 millisecondes se sont écoulées. Je creuserais plus profondément, mais je peux aussi supposer que tout timeout les occurrences ont néanmoins été masquées pendant les 4 secondes complètes.

Lorsque Optimize est chargé à l’aide d’une balise Google Tag Manager, la page est masquée pendant 964 millisecondes en moyenne. Lorsqu’il est chargé avec l’extrait de code en ligne asynchrone, il est masqué pendant 581 millisecondes en moyenne.

Résumé

C’est une configuration assez compliquée, mais le but n’est pas de faire cela pour chacune de vos expériences. C’est pour satisfaire votre curiosité de savoir si l’extrait anti-scintillement dégrade ou non l’expérience utilisateur, et cela vous donne juste un variable à utiliser (délai moyen d’affichage de la page).

Ce n’est pas sans défauts – la minuterie démarre lorsque l’extrait anti-scintillement est exécuté en haut de <head>alors qu’en réalité, il ne devrait commencer que lorsque la page serait normalement produire le premier élément visible (Première peinture contente).

L’analyse est également détachée – le simple fait de connaître le délai n’est pas si intéressant. Ce qui le rendrait plus significatif, c’est de voir si la durée de l’effet anti-scintillement avait un impact sur la façon dont l’utilisateur interagit avec le site. Il est possible qu’un long retard dans la peinture de la page puisse amener l’utilisateur à revenir à la page précédente, car il pourrait supposer que la page ne fonctionne pas.

Juste pour insister sur le sujet : cet article vous a montré une méthodologie que vous pourriez potentiellement utiliser pour mesurer l’effet des efforts d’atténuation du scintillement dans les tests A/B côté client. Le scintillement est un problème, et savoir comment beaucoup d’un problème est la première étape pour le résoudre.

Faites-moi savoir dans les commentaires si vous avez des suggestions pour améliorer l’expérience !

Source : www.simoahava.com

Articles similaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bouton retour en haut de la page
Index