web-dev-qa-db-fra.com

Le chargement de Google Analytics après le chargement de la page en ajoutant un script dans la tête ne fonctionne pas toujours

Dans l'UE, il existe une loi sur les cookies qui vous oblige à charger des scripts tiers après que l'utilisateur a exprimé son consentement, en cliquant, en faisant défiler ou en naviguant par exemple. Je charge donc 3 scripts en exécutant une fonction appelée après le chargement des documents. Voici le code:

enter image description here

Le problème est que cela ne fonctionne pas toujours, ni échoue toujours. Je vois des sessions et des activités mais je sais aussi qu'il y a des visites qui ne déclenchent pas les scripts parce que lorsque je les ai testées moi-même sur plusieurs autres ordinateurs, toutes les activités n'ont pas été enregistrées dans l'analyse.

Que dois-je corriger dans la fonction pour qu'elle fonctionne tout le temps?

25
frenchie
$(document).ajaxComplete(function() {
        var _gaq = _gaq || [];
      _gaq.Push(['_setAccount', 'UA-XXXXX-X']);
      _gaq.Push(['_trackPageview']);

       var loadGoogleAnalytics = function(){
         var ga = document.createElement('script');
           ga.type = 'text/javascript';
           ga.async = true;
           ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

           var s = document.getElementsByTagName('script')[0];
           s.parentNode.insertBefore(ga, s);
        }
    });
11
Farhad Bagherlo

L'autre réponse semble viser ga.js, qui est hérité, tandis que votre question semble être orientée vers analytics.js (actuel).

En étudiant un peu l'extrait analytics.js, vous pouvez facilement trouver une réponse (ci-dessous, formatée avec plus jolie):

(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-XXXXX-Y", "auto");
ga("send", "pageview");

L'astuce est simple: Google crée une variable globale _ GoogleAnalyticsObject qui est une chaîne représentant le nom de GoogleAnalytics global. Vous pouvez voir que par défaut c'est "ga".

Donc, au chargement, vous devez créer deux vars globaux: GoogleAnalyticsObject qui est une chaîne et une fenêtre [GoogleAnalyticsObject] qui est la fonction (qui accumule simplement les événements, cette fonction est remplacée lorsque la bibliothèque est chargée, je suppose). Ensuite, lorsque votre utilisateur accepte les cookies, vous pouvez charger la bibliothèque et vous avez terminé :)

5
adz5A

Vous pouvez essayer d'utiliser cette fonction qui me convient:

function loadGoogleAnalytics(trackingId) {
                var deferred = $q.defer();

                function loadScript() {
                    var scriptId = 'google-analytics';

                    if (document.getElementById(scriptId)) {
                        deferred.resolve();
                        return;
                    }

                    var s = document.createElement('script');
                    s.id = scriptId;
                    s.innerText = "(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', '" + trackingId + "', 'auto');";

                    // most browsers
                    s.onload = initGA();
                    // IE 6 & 7
                    s.onreadystatechange = function () {
                        if (this.readyState == 'complete') {
                            initGA();
                        }
                    }

                    document.getElementsByTagName('head')[0].appendChild(s);
                }

                $window.initGA = function () {
                    deferred.resolve();
                }

                loadScript();

                return deferred.promise;
            }
4
Leonardo Oliveira

Pourriez-vous essayer d'ajouter ce qui suit au lieu d'un appel à .innerHTML()

//...text above...
TheAnalyticsScript.text = ['ga-script-string', 'fb-script.string','hotjar.string'].join('\n');
$('body').append(TheAnalyticsScript);

Permettez-moi de savoir si cela fonctionne.

4
tyskr

Si vous regardez this post, vous pouvez le modifier légèrement pour obtenir ce que vous voulez:

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.Push(['_setAccount', 'UA-XXXXX-X']);
  _gaq.Push(['_trackPageview']);

   var loadGoogleAnalytics = function(){
     var ga = document.createElement('script');
       ga.type = 'text/javascript';
       ga.async = true;
       ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

       var s = document.getElementsByTagName('script')[0];
       s.parentNode.insertBefore(ga, s);
    }
</script>

Ensuite, appelez simplement loadGoogleAnalytics() chaque fois que l'utilisateur est d'accord avec votre affichage d'utilisation des cookies

4
wjvander

Voici mon choix sur le problème. La solution patche simplement les scripts par défaut pour renvoyer la fonction qui ajoute ensuite la balise script uniquement une fois le consentement accordé. Regarde:

// for GoogleAnalytics
var loadGA = (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();

  // call this function after receiving consent
  return function loadGA() {
    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');

// for Facebook
window.fbAsyncInit = function() {
  FB.init({
    appId: 'your-app-id',
    autoLogAppEvents: true,
    xfbml: true,
    version: 'v2.10'
  });
  FB.AppEvents.logPageView();
};

var loadFB = (function(d, s, id) {
  //- call this function after receiving consent
  return function loadFB() {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) {
      return;
    }
    js = d.createElement(s);
    js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }
}(document, 'script', 'facebook-jssdk'));

// for HotJar
var loadHJ = (function(h, o, t, j, a, r) {
  h.hj = h.hj || function() {
    (h.hj.q = h.hj.q || []).Push(arguments)
  };
  h._hjSettings = {
    hjid: 1,
    hjsv: 5
  };

  return function loadHJ() {
    a = o.getElementsByTagName('head')[0];
    r = o.createElement('script');
    r.async = 1;
    r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
    a.appendChild(r);
  }
})(window, document, '//static.hotjar.com/c/hotjar-', '.js?sv=');

// finally when you receive the consent
function onConsentReceived() {
  loadGA();
  loadFB();
  loadHJ();
}

//- meanwhile you can continue using ga(), hj() whatever here...

Chacun des chargeurs peut être dans sa propre balise script mais assurez-vous de l'ordre de ces balises.

3
riyaz-ali

Plutôt que d'ajouter l'intégralité du script d'analyse, vous pouvez toujours l'inclure, mais supprimez la ligne suivante:

ga("send", "pageview");

Ensuite, lorsque l'utilisateur accepte les cookies .. déclenchez la fonction d'analyse qui envoie la balise en utilisant la même ligne ci-dessus. Analytics n'envoie en fait aucune donnée, sauf indication contraire. Ce serait la façon la plus logique de faire ce que vous tentez.

0
Steve North

En pensant à ce que fait votre code, cette fonction:

  1. Crée un <script> élément rempli de chaînes
  2. L'ajoute au <head>

Notez que le <head> est afaik censé être chargé uniquement à la charge initiale. Selon l'implémentation du navigateur, etc., il se peut que certains navigateurs de votre visiteur ignorent le <script> tag que vous ajoutez une fois le chargement de la page terminé.

Si je comprends quand vous voulez bien faire, vous voulez:

  1. Pour charger la page sans les scripts de suivi
  2. Afficher un modal/popup de consentement
  3. Cliquez sur "Accepter" pour déclencher cette fonction sans un rechargement de page

remarque: de nombreux sites Web de l'UE rechargent la page après le consentement des cookies, car ils ajoutent le <script> tags avec suivi de la page à l'aide du rendu backend. En cliquant souvent sur "J'accepte les cookies", ils stockent un agreed: true tapez un cookie qui modifie la page Web que leur serveur envoie.

Si vous ne vous souciez pas des rechargements:

  1. Définir un cookie lorsque l'utilisateur accepte
  2. Recharge la page
  3. Demandez à votre backend (php/node/Ruby/autre) d'ajouter une balise de script basée sur ce cookie

Si vous vous souciez

Modifiez votre fonction pour exécuter les codes de suivi au lieu de les ajouter au DOM.

Il suffit de regarder les codes de suivi et de les décomposer en un code facile à lire. Par exemple, le code Ga est en fait simplement:

var ga = document.createElement('script')
ga.type = 'text/javascript'
ga.async = true
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

Puis

function addTrackers() {

// Execute the tracking things instead of adding them to the DOM

}
0
Mentor