Wednesday, January 18, 2012

Track KISSInsights surveys with Google Analytics

[UPDATE - January, 19th 2012] I update the code so it is compatible with all question type.

[UPDATE - January, 25th 2012] I fix two bug. 1) Now the GA event is fire. 2) surveyId extraction is cleaner.

[UPDATE - February, 23th 2012] Added some screenshot from Google Analytics

For a while, I searched a way to track KISSInsights with Google Analytics (GA). I wished to use the GA _trackEvent tag to capture the actual question/answer.

Here the code (using jQuery):


// This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// Fire when the user submit the survey.
_kiq.push(['eventHandler', 'submit', function(){ 

  // Retrieve KISSIsights survey ID.
  surveyId = $("[src*='kissinsights.com']").attr("src").match(new RegExp("(id=)([0-9]*)&"))[2];
  
  // For each survey questions...
  for (i = 0; i < $("[class*='ki_question']").length; i++) {
    // ... get the question text...
    question = $("[class*='ki_h1']:eq("+i+")").text();
  
    // ... and the selected anwser text
    // Check first for radio button answer.
    anwser = $("[class*='ki_question']:eq("+i+") input:checked[type='radio']").closest("label").text();
    
    // Then for checkbox answer
    if (anwser == "" || anwser == null || anwser == undefined) {
      anwser = $("[class*='ki_question']:eq("+i+") input:checked[type='checkbox']").closest("label").text();
    }
    
    // Then for textbox answer(s)
    if (anwser == "" || anwser == null || anwser == undefined) {
      anwser = $("[class*='ki_question']:eq("+i+") textarea").val();
    }
    
    // And finaly, score
    if (anwser == "" || anwser == null || anwser == undefined) {
      anwser = $("[class*='ki_question']:eq("+i+") [class*='active'] a").text();
    } 
  
    // If both data are available, queue a Google Analytics _trackEvent tag.
    if (question && anwser) _gaq.push(['_trackEvent', 'VOC', surveyId, question +' | ' + anwser]);
  }

}]);

Basically, this code is trigger when a user submit his answer. It will create a _trackEvent tag for each question/answer(s) pair. The beauty of the code is that it fetch the actual text value automatically and save it in a readable way into GA.

  • Event category: Always VOC (you can change it to any thing you like.)
  • Event action: The actual survey id (so if you have multiple survey running at the same time, each one would be save separately in GA.)
  • Event label: "Question text | Answer(s) text"

Doing so, I could then create segments and custom reports in Google Analytcs base on that Voice of Customer (VoC) data.

For example:

  • Which traffic source yield better satisfaction?
  • Does satisfaction impact goal completion rate?
  • Does satisfaction impact frequency/recency of visitor?

Here a example on how to create a custom report in Google Analytics to categorize outcome base on survey answer.

And here a example directly from the Google Analytics Events report.

Enjoy and feel free to let me know/share if you like :-)

[UPDATE - January, 20th 2012] You could easily modify the tracking to use an alternate version. Your choice.

if (question && anwser) _gaq.push(['_trackEvent', 'VOC-' + surveyId, question, anwser]);
  • Event category: VOC-surveyID (so if you have multiple survey running at the same time, each one would be save separately in GA.)
  • Event action: Question text
  • Event label: Answer(s) text

Saturday, February 5, 2011

How to use jQuery to automate page tagging

Hello,

Here a jQuery script to help you tag your pages. Here, I use Coremetrics Event tagging, but you could also easily modify this script to use Google Analytics or any other web analytics solution.

Basicly, this script scan the page for find link that must be tagged (as define in tagList array). If the link already contain a event tag, this link is skipped. Coremetrics have a system to initiate event tag, so once the tagging is added to the onclick and onkeypress DOM event, the event is then initiated once.

// Licensed under the GPL Version 2 licenses.
try {
  // Make sure JQuery doesn't conflict with other JavaScript libraries. (Should be use just after the libraries declaration.)
  jQuery.noConflict();
  
  // Array containing conversion event tag information.
  //   - URL to look for. (See note)
  //   - Conversion event name.
  //   - Conversion event categories name.
  //   - Conversion event point when initialized.
  //   - Conversion event point when completed.
  // Note: The order in the array is important.
  // For example, don't put "/stores/" before "/stores/locator.html".
  var tagList = [
    ['/contact-us/', 'Contact us', 'Call-to-action', '0', '10'],
    ['/online-application/', 'Apply online', 'Call-to-action', '0', '100']
  ];

  // List the detected tags that must be initiated.
  var tagDetected = [];

  // Check for link that need to be tagged. Make sure is not already tagged.
  jQuery(document).ready(function(){
    jQuery("a:not([onclick*='cmCreateConversionEventTag'])").each(function(index) {
      if (this.href != '') {
        var i = findConversionLink(this.href);
        if (i != -1) {
          // Check if that tag have been already detected (so we won't initialize the same tags multiple time.)
          if (jQuery.inArray(i, tagDetected) == -1) {
             tagDetected.push(i);
          }
        }
      }
    });

    // Founded some tag that need to be initiated?
    if (tagDetected.length > 0) {
      for (var i = 0; i < tagDetected.length; i++) {
        for (var j = 0; j < tagList.length; j++) {
          if (j == tagDetected[i]) {
              cmCreateConversionEventTag(tagList[j][1], "1", tagList[j][2], tagList[j][3]);
          }
        }
      }
    }

    // Add the conversion event tag to the onlick and onkeypress event of the link (if not already present)
    jQuery("a:not([onclick*='cmCreateConversionEventTag'])").live('click keypress', function() {
      var i = findConversionLink(this.href);
      if (i != -1) {
        cmCreateConversionEventTag(tagList[i][1], "2", tagList[j][2], tagList[i][4]);
      }
    });
  });

  // Check if a URL exsit in the array.  If so, return "first" founded index.
  // This is why we need to put "/stores/locator.html" before "/stores/" in the tagList array.
  function findConversionLink (a_sURL) {
    for (var i = 0; i < tagList.length; i++) {
      if (a_sURL.indexOf(tagList[i][0]) != -1) {
        return i;
      }
    }
    return -1;
  }

}
catch (err) {
  // Do nothing.
}

Let me know if you found this script useful.

Wednesday, February 2, 2011

Taggage automatique de liens d'événement avec jQuery

Imaginons que vous devez tagger un site de 20 000 pages et devez ajouter des tags d'évènemet sur celles-ci. Que de travail.

Voici un bout de code en jQuery que j'ai developper pour m'aider à faire exactement ça. Ici, le taggage est effectué avec Coremetrics, mais il serait très facile de modifer ce code pour n'importe quel autres tags.

// Licensed under the GPL Version 2 licenses.
try {
  // Make sure JQuery doesn't conflict with other JavaScript libraries. (Should be use just after the libraries declaration.)
  jQuery.noConflict();
  
  // Array containing conversion event tag information.
  //   - URL to look for. (See note)
  //   - Conversion event name.
  //   - Conversion event categories name.
  //   - Conversion event point when initialized.
  //   - Conversion event point when completed.
  // Note: The order in the array is important.
  // For example, don't put "/stores/" before "/stores/locator.html".
  var tagList = [
    ['/contact-us/', 'Contact us', 'Call-to-action', '0', '10'],
    ['/online-application/', 'Apply online', 'Call-to-action', '0', '100']
  ];

  // List the detected tags that must be initiated.
  var tagDetected = [];

  // Check for link that need to be tagged. Make sure is not already tagged.
  jQuery(document).ready(function(){
    jQuery("a:not([onclick*='cmCreateConversionEventTag'])").each(function(index) {
      if (this.href != '') {
        var i = findConversionLink(this.href);
        if (i != -1) {
          // Check if that tag have been already detected (so we won't initialize the same tags multiple time.)
          if (jQuery.inArray(i, tagDetected) == -1) {
             tagDetected.push(i);
          }
        }
      }
    });

    // Founded some tag that need to be initiated?
    if (tagDetected.length > 0) {
      for (var i = 0; i < tagDetected.length; i++) {
        for (var j = 0; j < tagList.length; j++) {
          if (j == tagDetected[i]) {
              cmCreateConversionEventTag(tagList[j][1], "1", tagList[j][2], tagList[j][3]);
          }
        }
      }
    }

    // Add the conversion event tag to the onlick and onkeypress event of the link (if not already present)
    jQuery("a:not([onclick*='cmCreateConversionEventTag'])").live('click keypress', function() {
      var i = findConversionLink(this.href);
      if (i != -1) {
        cmCreateConversionEventTag(tagList[i][1], "2", tagList[j][2], tagList[i][4]);
      }
    });
  });

  // Check if a URL exsit in the array.  If so, return "first" founded index.
  // This is why we need to put "/stores/locator.html" before "/stores/" in the tagList array.
  function findConversionLink (a_sURL) {
    for (var i = 0; i < tagList.length; i++) {
      if (a_sURL.indexOf(tagList[i][0]) != -1) {
        return i;
      }
    }
    return -1;
  }

}
catch (err) {
  // Do nothing.
}

Ce javascript inspecte chacun des liens dans une page et vérifie si celui-ci ne contient pas déjà un tag d'évènements mais devrais en contenir un. Si il en trouve, il l'ajoute au onclick et au onkeypress et initialise celui-ci ensuite.

Amusez-vous bien et laisser moi savoir ce que vous en pensez.

Friday, July 9, 2010

Profit net et analyse web

Mon billet d'aujourd'hui est inspiré d'un article d'Avinash Kaushik

Retour aux bases

D'abord, un petit retour aux bases des "affaires". L'objectifs des entreprises est d'augmenter ses profits nets. Ceux-ci sont calculés de la manière suivante : la marge de profit x le volume vendu. La marge de profit correspond aux profits moins les coûts et le volume peut être défini de la manière suivante, part de marché x la taille du marché. Assez simple.







Nous avons donc 4 dimensions sur lesquelles jouer. Les stratégies d'affaires doivent tourner autour de ces 4 points centraux. L'optimisation d'une seul de ces 4 dimensions aura un impact positif sur les profits nets.


Stratégies

Profit
  • Somme-nous compétitifs (prix et qualité de service)?
  • Offrons-nous des incitatifs financiers (rabais) pour pousser les gens vers les canaux les plus rentables?

Coût
  • Le coût unitaire est variable selon les canaux. Un produit acheté en ligne de manière autonome nous coûte moins cher qu'un produit acheté en magasin (réseau physique).
  • Optimiser nos campagnes marketing afin d'avoir la même performance avec un canal marketing pour une fraction du prix d'un autre (achat de mots-clés vs bannières par exemple). Bref, diminuer le coût d'acquisition.
  • Peut-ont améliorer nos processus pour les rendre plus efficaces?

Notre part de marché
  • Notre part de marché au Québec est très grande, peut-on l'élargir encore? L'apparition du virtuel va t'il faire disparaître notre plus gros avantage? (présence physique Au-Lac-À-la-Tortue par exemple)
  • Pouvons-nous cibler des gens ailleurs (via Facebook, Twitter, etc)
  • Augmentation de la satisfaction de nos clients (un client satisfait reviendra acheter, nous n'aurons pas à augmenter notre budget marketing pour aller chercher de nouveaux clients afin de remplacer cette business.)

Taille du marché
  • Notre marché est surtout au Québec. Qu'en est-il de nos offensives hors-Québec? Peut-on mesurer celles-ci?
  • Création de nouveaux produits/services.


Et l'analyse web dans tout ça?

Le rôle d'un analyste web est de mesurer et optimiser le canal web. Pour ce faire, nous nous mesurons à des objectifs d'affaires en lien avec les 4 dimensions nommées précédemment.

Par exemple :

Profit : Est-ce que le volume de vente généré par un rabais, éclipse le coût de celui-ci? (A/B testing de l'offre, 5% de rabais VS 10% de rabais, etc)
Coût : Calculer les coûts d'acquisition par canal. (achat de mots-clés VS bannières VS programmes affiliés)
Part de marché : Analyse de la part de marché dans les engins de recherche (SEO et PPC)
Taille du marché : Évaluation des performances des canaux sociaux (Facebook, Twitter, etc.)

Voila pourquoi il est important d'avoir des objectifs d'affaires précis et mesurables. Une fois ces objectifs identifiés, des indicateurs y correspondant doivent être suivis et utilisés par les bonnes personnes. La prise de décision s'en trouvera simplifiée.

Et vous, qu'en pensez-vous?

Thursday, June 24, 2010

Petite série sur Facebook

J'ai créer 4 petits billets concernant Facebook.


  1. Comment créer une page personnalisé dans votre Fan page Facebook

  2. Faites de la promotion directement dans Facebook

  3. Facebook Insights (le prochain Google Analytics?)

  4. Le nouveau Facebook Insights



Bonne lecture :-)

Faites de la promotion directement dans Facebook

Le modèle publicitaire de Facebook est CPC, un peu comme Google AdWords (il est aussi possible d'utiliser un modèle CPM, mais je le déconseilles.)




Étant sociaux, Facebook permet la création de promos qui cibles les gens selon leurs intérêts, localisation, études, démographie, etc. Donc, trafic hautement qualifié selon la campagne. Ce trafic peut être dirigé sur une fans page ou sur votre site principale (n'oubliez pas de mettre des codes de campagnes.)




N'essayer pas que votre trafic cible viennent à votre rencontre, allez à la rencontre de celui-ci.

Comment créer une page personnalisé dans votre Fan page Facebook

Si vous avez une fan page Facebook, il est possible d'y créer une page (onglet) entièrement personnalisé.







Pour ce faire, vous devrez utiliser une "application de page" appelé Static FBML. Il est possible d'inclure des tags HTML et des tags FBML. Le FBML est un peu comme le HTML mais permet de faire des trucs plus spécifique à Facebook, comme contrôler une partie de la page selon le type de visiteurs (fan VS non-fan, 18 ans et plus ou non, etc).




Veuillez noter que certaines restrictions s'appliquent. Par exemple, il est possible d'y inclure du Flash et du JavaScript, mais un intervention par le visiteur est nécessaire pour que le tout débute (habituellement un clic.) Par exemple, si vous ajouter un bandeau Flash, l'internaute devra cliquer sur une image avant de pouvoir afficher celui-ci (à la place de l'image.)

Le nouveau Facebook Insights

Facebook à créer une nouvelle version (encore beta) de son outil d'analyse web Insights. Cette nouvelle mouture est plus facile à lire visuellement et offre maintenant la possibilités de connaitre le nombre de page vues pour une page spécifique, ce qui n'est pas possible dans la version actuel (voir mon billet précédent.)

Encore une fois, pour les curieux, voici une capture d'écran.

Facebook Insights (le prochain Google Analytics?)

Pour ceux d'entre vous qui avez créé une Fan page sur Facebook, vous savez peut-être que Facebook inclus dorénavant un interface d'analyse web.

Il est possible avec cet outil de connaitre la démographie de nos visiteurs et fans, de connaitre l'achalandage général sur ces pages et le nombre de consommation médias (audio, vidéos, photos). Ces données restent pour le moment très sommaire, mais c'est mieux que rien. Si en plus, vous utiliser des codes de campagnes pour vos liens pointant sur votre site principale, vous aurez une bonne idée de l'impact de votre initiative social.

Pour les curieux, voici des captures d'écran qui montre les données disponibles.




























Monday, April 19, 2010

Projet Annabel Robitaille - Syndrome CHARGE

Bonjour à tous,

Un ami à moi a besoin d'aide. Leur fille est née avec le syndrome de CHARGE. Durant 10 mois, elle à déjouer la mort à Sainte-Justine. Elle est enfin retourné à la maison depuis, mais sa mère a dû quitter son emploi pour s'occuper de leur fille Annabel à temps plein. Dernièrement, des problèmes de moisissure (très problématique pour Annabel) oblige des rénovation estimé à 50 000$ sur la maison. Il est possible de faire un don en ligne sécuritairement via le site de Sainte-Justine. Un concert bénéfice auras aussi lieu au Palace de Granby le 24 mai. La soirée sera animée par Bruno Landry et plusieurs artistes reconnus, dont Jean-Marc Chaput, Martin Dubé, Dan Bigras et Hugo Lapointe ont déjà accepté de participer au spectacle. Les billets pour le spectacle sont au prix de $ 28.50.

Site officiel du projet Annabel Robitaille
http://www.annabelrobitaille.com/

Lien vers la page de don via Sainte-Justine
http://activites.fondation-sainte-justine.org/fr/groupes/v/c1563567a4

Spectacle bénéfice à Granby
http://www.palacedegranby.com/billet/spectacle/spectacles/annabel-robitaille/projet-annabel-robitaille.aspx?DateID=231


Annabel est née le 5 septembre 2008 avec une maladie rare : le syndrome CHARGE, maladie qui atteint environ 1 enfant sur 100 000. Arrêt respiratoire, réanimation cardiaque, intubation, mise sous oxygène, telles ont été ses premières minutes de vie. Elle avait 12 heures de vie quand l’ambulance du CHU Ste-Justine est venue la chercher à l’hôpital de Granby. Son arrivée à la maison avec sa famille s’est produite seulement le 22 juillet 2009.

Après plusieurs opérations et 10 mois et demi à Ste-Justine, Annabel est avec nous depuis 8 mois. Malgré sa trachéostomie, sa gastrostomie et toutes ses anomalies dûes au syndrome, son évolution est constante. Ayant souvent frôlé la mort de près, elle se bat depuis sa naissance. C’est maintenant notre tour ...

Depuis Noël, ils avons découvert des moisissures dans la chambre d’Annabel et ailleurs dans la maison, ce qui est très dangereux pour la demoiselle à la santé fragile. Une infiltration d’eau dans la toiture laisse aussi entrevoir la présence de moisissures dans l’entretoit. Le coût des réparations est estimé a environ 50 000 $ et ils n'ont pas les moyens de les réaliser. Toutefois, il est primordial de réparer et d’assainir la maison dès que possible avant que l’état de santé d’Annabel n’en souffre et qu’elle soit de nouveau hospitalisée à long terme.

Le syndrome CHARGE est en fait un acronyme :

C pour Colobomes (yeux),
H pour Heart (cœur),
A pour Atrésie des choanes (nez),
R pour Retard global de développement,
G pour organes Génitaux et
E pour Ear (oreilles).

Heureusement, Annabel ne possède pas toutes ses anomalies et celles qu’elle a ne sont pas toutes aussi sévères les unes que les autres. D’autres problèmes se rajoutent à la condition d’Annabel et découlent du syndrome dont elle est atteinte :

- Une malformation au larynx l’empêchait de respirer normalement. Suite à deux opérations pour corriger la situation, il lui était encore impossible de respirer tout à fait par elle-même alors en février 2009, son ORL a procédé à une trachéostomie (trou dans la gorge pour laisser passer l’air) qu’elle a toujours en ce moment et pour encore plusieurs mois et/ou années selon comment elle évoluera.

- Une absence du réflexe de déglutition servant à s’alimenter. N’ayant pas assez de forces pour respirer normalement, Annabel n’était pas en mesure de téter quoi que ce soit pour se nourrir alors dès sa naissance, elle a été alimentée par gavage au moyen d’un tube passant par le nez et se rendant à l’estomac.

Encore maintenant, elle est toujours gavée mais au moyen d’une gastrostomie (bouton donnant accès à l’estomac) plutôt qu’à l’aide du tube naso-jéjunal. Lui apprendre ce qu’est de la nourriture sera l’un des prochains défis si les médecins donnent leur accord dans les prochains mois.
m
- La trachéostomie étant une ouverture pratiquée plus bas que les cordes vocales, il n’y a pas d’air qui passe au travers d’elles. En conséquence, Annabel n’émet aucun son, aucun bruit, aucun pleur. Annabel a 18 mois et nous ne l’avons jamais entendue pleurer. Cela a pour effet que les parents doivent avoir en tout temps un contact visuel avec elle afin de s’assurer qu’elle va bien.

- L’ensemble des handicaps d’Annabel font que nous devons lui apporter des soins 24 heures sur 24, 7 jours sur 7. Il faut notamment nettoyer la trachéostomie, l’hydrater pour ne pas que les sécrétions durcissent et obstruent l’entrée d’air, aspirer les sécrétions qu’Annabel ne parvient pas à tousser ou à éternuer correctement par elle-même, etc. Il faut aussi s’occuper de ses gavages, de ses exercices quotidiens de physiothérapie et de tous ses rendez-vous médicaux qui sont nombreux, tant à Granby qu’au CHU Ste-Justine.

Je vous remercie !