Posts tagged "data Viz"

Comparer simplement vos tunnels de conversion Piano Analytics

Petit rappel sur la fonctionnalité Tunnel

Nous avions vu dans un article précédent comment la nouvelle fonctionnalité « Tunnel » de Piano Analytics permettait de renforcer les analyses de séquences déjà disponibles dans l’interface. En effet, celle-ci propose de visualiser les volumes, les taux de passages et le temps moyen pour des séquences de plusieurs évènements ou groupes d’évènements que vous allez pouvoir définir :

Comment comparer plusieurs tunnels, sur la métrique de son choix ?

Après plusieurs semaines d’utilisations, j’ai rencontré certains use cases que je ne parvenais pas à gérer à 100% juste via ce module. Les 2 principaux étant :

  • de pouvoir visualiser des métriques autres que uniquement le volume de visites/visiteurs/users (taux de passage, temps passé, taux de sortie)
  • de pouvoir comparer rapidement plusieurs tunnels, en faisant varier un élément.

Pour vous illustrer ces points, imaginez le cas suivant : j’ai 10 visuels d’auto-promotions différentes pour une campagne visant à générer des achats et, au-delà de connaître simplement leur taux/volume de conversions, je souhaite aussi pouvoir comparer leur performance à chacune des étapes de mon tunnel de conversion.

Remplacez maintenant « auto-promotions » par n’importe quel levier d’aide à la conversion comportant des variantes pour vous projeter dans cette problématique (landing pages, AB Test, campagnes de personnalisation…).

Il serait théoriquement possible de le faire, en réalisant manuellement les 10 tunnels, mais il faut bien avouer que cela est fastidieux et qu’un travail manuel de retraitement de la donnée sera de toute façon nécessaire. Et même en faisant cela, je n’aurais toujours pas le temps moyen passé entre chacune de mes étapes.

L’objectif de cet article

L’objectif de cet article va donc être de vous montrer comment exploiter l’API proposé par Tunnel pour automatiser cette tâche, et ainsi obtenir ce type d’information en très peu de temps. La démonstration se fera via Python, mais la logique est applicable au autres langages ou à l’outil de votre choix.

Nous obtiendrons donc :

  • Un tableau récapitulatif des métriques associées à chaque variante de notre tunnels,
  • Pour la métrique de votre choix, un histogramme de comparaison pour chaque variante,
  • Pour la métrique de votre choix, une carte de chaleur composée des étapes et des variantes de votre tunnel.

Pour cet exercice, nous prendrons le cas d’un tunnel composé des étapes suivantes :

  • Le visiteur clique sur une autopromotion, pouvant être présente un peu partout sur le site. J’ai 10 autopromotions différentes, que je voudrais faire varier,
  • Puis le visiteur affiche une page produit,
  • Puis le visiteur ajoute un produit au panier,
  • Puis le visiteur affiche le panier,
  • Puis finalement, le visiteur réalise un achat.

Voici le tunnel dans l’interface, où j’ai filtré sur une des dix auto-promotions en première étape :

Ce cas nous servira de base pour le reste de l’article.

Les données obtenues

Maintenant que nous avons notre cas pratique défini et avant de rentrer dans le code, projetons-nous dans le résultat que nous pouvons obtenir.

Tableaux récapitulatifs des campagnes

Le code retourne tout d’abord un tableau récapitulatif des 10 campagnes d’auto-promotions ayant initié la séquence, avec les métriques proposées par l’API :

  • Visites (nombre de visites ayant été jusqu’au bout du tunnel),
  • Exits (nombre de visites abandonnistes),
  • visits_conversion_rate (taux de conversion global du tunnel),
  • visits_exit_rate (taux de sortie global du tunnel),
  • min_timespent (temps le plus court enregistré pour réaliser le tunnel, en secondes),
  • max_timespent (temps le plus long enregistré pour réaliser le tunnel, en secondes),
  • avg_timespent (temps moyen pour réaliser le tunnel, en secondes).

Cela permet d’avoir un premier aperçu des performances de chaque campagne, et de repérer les métriques intéressantes.

Carte de chaleurs des tunnels

On remarque dans mon exemple que les taux de conversion sont disparates, selon la campagne qui a initié le tunnel. Je souhaite donc pouvoir isoler cette métrique, et l’afficher dans un histogramme :

En plus de cela, je souhaite avoir le détail des taux de passage, entre chacune des étapes.

Voici le résultat, mise en forme via une matrice colorimétrique (plus le taux de passage est important, plus la valeur tend vers le rouge) :

N.B : la première étape a 0 pour taux de conversion, puisque celle-ci ne comporte pas d’étape précédente.

Tunnel de conversion détaillé

Si je souhaite finalement zoomer sur un des tunnels, pour mieux appréhender les différences de valeurs, une dernière fonction me permet de l’afficher de manière plus visuelle :

Pour que vous compreniez mieux le rendu, voici un tunnel, mais cette fois-ci avec la métrique « visits » :

Guide d’utilisation du fichier Python

Maintenant que nous avons vu l’intérêt d’un tel retraitement de données, nous allons voir ensemble, comment utiliser le fichier.

Récupération de l’appel API dans Tunnel

Nous allons d’abord devoir générer un appel API « modèle », qui nous permettra ensuite d’automatiser l’ensemble des requêtes.

Pour cela, configurez votre tunnel comme bon vous semble (nombre d’étapes, filtres, segments…). Une contrainte à respecter : l’étape que vous souhaitez faire varier doit comporter un filtre « est égal à {{la valeur de votre choix}} ». La valeur en elle-même n’est pas importante puisque le script Python va la dynamiser. Voici un exemple :

Une fois cela configuré, cliquez sur le bouton de partage :

Puis copiez la partie « Body », contenant tout le paramétrage API de votre tunnel, et mettez cela de côté dans un bloc-notes :

Récupération de la clé API

Pour requêter vos données Piano Analytics depuis l’extérieur de l’interface, vous allez devoir obtenir une clé API. Cette clé est liée à votre compte Piano Analytics, vous n’aurez donc pas la même que votre collègue. Vous aurez également accès au même périmètre que celui disponible dans votre interface (même liste de niveaux 1).

Une fois connecté à votre compte, allez dans votre profil puis dans l’onglet Api Keys.

 Générez une nouvelle clé et conservez bien l’Access key et surtout la secret key, qui ne vous sera plus donnée par la suite.

Configuration de votre script Python

Pour utiliser ce code, il vous faudra donc une instance Python disponible. Si vous n’en avez pas, vous pouvez utiliser Le service de notebook en ligne de Google.

Vous allez devoir paramétrer quelques variables afin de rendre le code fonctionnel, mais rien d’insurmontable :

  • key : votre clé API,
  • etape : numéro de l’étape qui doit être variabilisée (cela n’est pas obligatoirement la première étape),
  • propriete : nom de la propriété où vous avez placé le filtre « est égal » à variabiliser,
  • valeurs : liste des différentes valeurs que prendra le filtre « est égal ». Pas de limite dans le nombre de valeurs, retenez juste que chaque valeur va générer un appel API. Donc plus il y a de valeurs, plus le temps d’exécution du script sera important,
  • NomsEtapes : vous pouvez renommer les différentes étapes de votre tunnel, afin que cela soit plus parlant lors de la lecture des graphiques…Attention, le nombre de valeurs dans la liste doit exactement correspondre au nombre d’étapes de votre tunnel,
  • jsonFromDQ : reprendre exactement le Json que vous avez récupéré de Data Query à l’étape précédente.
key = "votre_cle_API"
etape = 1
propriete = 'onsitead_format'
valeurs = ["Campagne 1", "Campagne 2", "Campagne 3", "Campagne 4", "Campagne 5", "Campagne 6", "Campagne 7", "Campagne 8", "Campagne 9", "Campagne 10"]
nomsEtapes = ['clic autopromo','page_produit','ajout_panier','page_panier','achat']
jsonFromDQ = {
  "funnel": {
    "scope": "visit_id",
    "steps": [...

Exécutez maintenant le script principal, qui va de manière schématique boucler sur des appels API générés à partir de votre liste de valeurs, puis consolider le tout dans un grand tableau (dataframe Pandas).

Visualisation des données

Comme nous l’avons vu, plusieurs méthodes et fonctions sont à votre disposition pour récupérer l’information. Parcourons-les ensemble.

Les tableaux récapitulatifs

Pour afficher les tableaux récapitulatif des tunnels, il faut cibler la variable globalData, qui va contenir 2 tableaux.

globalData[1] va contenir les chiffres globaux pour chaque tunnel :

globalData[0] va contenir le tableau « brut » de tous les tunnels (si vous souhaitez retravailler les données d’une autre manière) :

Les graphiques

La fonction displaygraph() va afficher 2 graphiques :

  • Un histogramme de comparaison des tunnels sur la métrique de votre choix (trié par valeur décroissante),
  • Une matrice colorimétrique, qui affiche la métrique pour chaque tunnel et chaque étape de votre tunnel.

Vous pouvez personnaliser le 2ième argument de la fonction avec le nom de votre métrique parmi celles disponibles.

Finalement, la fonction detailFunnel() vous permet d’avoir le détail d’un des tunnels, sur la métrique de votre choix. Il y a ici 2 arguments personnalisables :

  • le 2ième, permettant de sélectionner le tunnel de votre choix,
  • le 3ième, permettant de sélectionner la métrique de votre choix.

Conclusion

En conclusion, Tunnel est un outil très utile pour l’analyse de séquences d’événements, mais il peut être limité en termes de métriques disponibles et de comparaison. Cet article a montré comment exploiter l’API proposée par Tunnel pour automatiser cette tâche et obtenir rapidement des informations telles que des tableaux récapitulatifs des métriques associées à chaque variante de Tunnel, des histogrammes de comparaison pour chaque variante, et des cartes de chaleur. Bien que le code présenté ici utilise Python, la logique peut être appliquée à d’autres langages et outils. Cette démonstration montre donc que Tunnel n’est qu’un point de départ vers d’autres analyses plus poussées.

Code source

Voici le code source permettant de récupérer les données de votre scénario d’analyse et d’afficher les graphiques de votre choix :

import pandas as pd
pd.options.mode.chained_assignment = None 
import requests
import json
import numpy as np
import datetime
import time
import re
import plotly.express as px

######## Partie configuration

key = "123ABC" # Votre clé API
etape = 1 #Le numéro de l'étape qui va être variabilisé
propriete = 'onsitead_format' # Nom de la propriété où vous avez placé le filtre "est égal" à variabiliser
valeurs = ["Campagne 1", "Campagne 2", "Campagne 3"] # liste de valeurs qui seront placées dans les filtres de l'étape
nomsEtapes = ['clic autopromo','page_produit','ajout_panier','page_panier','achat'] #vous pouvez renommer les différentes étapes de votre tunnel
jsonFromDQ = { #reprendre exactement le Json que vous avez récupéré dans Data Query
  "funnel": {
    "scope": "visit_id",
    "steps": []
      }
    }

######## Partie déclaration et excecution des données
def apiCall(apikey, url):
  headers = {
    'x-api-key': apikey
  }
  call = requests.get(url, headers=headers)
  data = json.loads(call.content)
  return data

def jsontoTab(json):
  steps = {k: v for k, v in json['DataFeed']['Rows'][0].items() if k.startswith('m_step')}
  tab = []
  ModelingStep = {}
  for step in steps:
    splitKey = step.split('_')
    ModelingStep = {
        '_'.join(splitKey[2:len(splitKey)]) : steps[step],
        'step': int(splitKey[1].split('step')[1])
    }
    tab.append(ModelingStep)
  finalTab = pd.DataFrame(data=tab).groupby(['step']).sum().reset_index()
  return finalTab

def jsontoTabGlobal(json):
  steps = {k: v for k, v in json['DataFeed']['Rows'][0].items() if k.startswith('m_global')}
  newDict = {}
  for step in steps:
    newDict[step.split('m_global_')[1]] = steps[step]
  final = pd.DataFrame(data=newDict,index=[0])
  return final

def urlBuilder(url,step,prop,filter):
    NewDict = url
    NewDict['funnel']['steps'][step-1]['condition']['filter']['$and'][1][prop]['$eq'] = filter
    toStr = json.dumps(NewDict).replace(" ", "")
    urlFinal = 'https://api.atinternet.io/v3/data/getData?param='+toStr
    return urlFinal

def builder(initialUrl, stepToChange,propToChange,ListValues,stepNames):
  listTable = []
  listTableGlobal = []
  for value in ListValues:
    changedUrl = urlBuilder(initialUrl,stepToChange,propToChange,value)
    jsonRaw = apiCall(key,changedUrl)
    tableGlobal = jsontoTabGlobal(jsonRaw)
    tableGlobal['funnel_version'] = value
    tableGlobal['visits'] = ((tableGlobal['exits']/tableGlobal['visits_exit_rate'])-tableGlobal['exits']).round()
    tableGlobal= tableGlobal[['funnel_version','visits','exits','visits_conversion_rate','visits_exit_rate','min_timespent','max_timespent','avg_timespent']]
    listTableGlobal.append(tableGlobal)

    table = jsontoTab(jsonRaw)
    table['funnel_version'] = value
    table['step_name'] = ''
    for i in range(len(stepNames)):
      table['step_name'][table['step'] == i+1] = stepNames[i]
    table = table[['funnel_version','step','step_name','visits','min_timespent','max_timespent','avg_timespent','visits_exits','visits_conversion_rate','visits_exit_rate']]
    listTable.append(table)
  return [pd.concat(listTable),pd.concat(listTableGlobal)]

def displaygraph(data,metric,values):
    fig1 = px.bar(data[1].sort_values(by=[metric], ascending=False), x='funnel_version', y=metric)
    fig1.show()

    globalvalues = []
    for value in values:
      valueList = list(data[0][data[0]['funnel_version'] == value][metric])
      globalvalues.append(valueList)
    fig2 = px.imshow(globalvalues,
                labels=dict(x="Etapes", y="Variante", color=metric),
                color_continuous_scale='RdBu_r',
                x=nomsEtapes,
                y=values,
               text_auto=True,
               width=1000, 
               height=650)
    fig2.update_xaxes(side="top")
    fig2.show()
  
def detailFunnel(data,funnel,metric):
  fig = px.funnel(data[data['funnel_version'] == funnel], x='step_name', y=metric)
  fig.show()
  
globalData = builder(jsonFromDQ,etape,propriete,valeurs,nomsEtapes)

####################### partie visualisation

globalData[0] #Va contenir le tableau "brut" de tous les tunnels
globalData[1] #Va contenir les chiffres globaux pour chaque tunnel
displaygraph(globalData,'visits_conversion_rate',valeurs) #affiche l'hisgramme récap et la matrice colorimétrique, en fonction de la métrique de votre choix
detailFunnel(globalData[0],'Campagne 8','visits') #Donne le détail d'un des tunnels, en fonction de la métrique de votre choix