Alexis Rylko - Consultant SEO

Comment faire une étude du taux de clic SEO (avec R)? Derrière les coulisses de notre étude

Il y a quelques mois nous avons publié notre étude du taux de clics en France sur le blog d’iProspect. La publication a suscité un vif intérêt, nous avons reçu pas mal de retours positifs, mais aussi de questions sur les aspects techniques et méthodologiques.

L’objectif de cet article est d’expliquer les différents choix méthodologiques que j’ai faits et aussi de partager les techniques concrètes qui vous permettraient de réaliser des études pareilles de votre côté.

Allez, c’est parti! Voici notre agenda, vous pouvez passer directement à la partie qui vous intéresse:

  1. Étapes et environnement de travail.
  2. Collecter les données de la Search Console (avec R).
  3. Traiter le dataset (avec R).
  4. Visualiser les résultats.

Étapes et environnement de travail

Comme dans la plupart des missions de la data science, pour faire une étude du taux de clics nous devons suivre 3 étapes:

  1. Collecter les données depuis la Search Console.
  2. Traiter les données (nettoyer, catégoriser, segmenter etc.)
  3. Visualiser avec de jolis graphiques pour pouvoir interpréter les résultats.

Avant de commencer, rappelons notre dataset  :

  • 200 sites;
  • 7,6 millions de mots clés;
  • 4,2 millions sont des mots clés uniques;
  • 2,1 milliards d’impressions;
  • 233 millions de clics.

Là, on n’est pas sur les chiffres énormes, mais ils dépassent déjà les limites imposées par Excel et Google Spreadsheets. De plus, traiter une feuille de calcul avec quelques millions de lignes sur Excel peut vite mettre en colère même les plus sereins de nous.

Toutes les opérations nécessaires ont été réalisé avec le langage R dans l’environnement Rstudio. C’est gratuit et R est bien adapté pour ce genre des tâches.

Ainsi pour commencer, il faut:

  1. Installer R
  2. Installer Rstudio

Comme j’avais pas mal de projets à scraper, j’ai également créé un compte gratuit sur rstudio.cloud ce qui a permis de requêter la Search Console en cloud sans charger ma machine.

Collecter les données de la Search Console avec R

Pour récupérer les données depuis la Search Console on va utiliser le package SearchConsoleR. On va l’installer, activer et s’authentifier avec notre compte Google.

Si comme moi, vous voulez récupérer les données de plusieurs voire de multiples sites, ça peut être pratique de commencer par exporter dans Rstudio toute la liste des sites présents dans votre compte:

#Installer le package Google Search Console pour R
install.packages("searchConsoleR", dependencies = TRUE)

#Activer le package
library(searchConsoleR)

#S'authentifier
scr_auth(new_user = TRUE)

#Exporter toute la liste de projets depuis Google Search Console 
restricted_websites <- subset(scr_websites, permissionLevel=="siteRestrictedUser") 
fullaccess_websites <- subset(scr_websites, permissionLevel=="siteFullUser") 
all_websites <- rbind(fullaccess_websites, restricted_websites)

Au niveau d’organisation dans Rstudio, on va dans un premier temps mettre chaque projet (site) dans une variable qu’on va plus tard réunir ensemble dans un seul dataset.

Pour exporter les données de la Search Console pour chaque site on va faire cette requête:

site_fr <- search_analytics(siteURL = "https://www.site.fr/",
                            startDate = Sys.Date() - 100,
                            endDate = Sys.Date() - 4,
                            dimensions = c("country","device","query"),
                            dimensionFilterExp = c("country==FRA"),
                            searchType = "web",
                            rowLimit = 10000)

Les valeurs dans « siteURL » et « rowLimit » sont à remplacer par l’url de votre propriété dans la Search Console et par un nombre approximatif de mots-clés y rattachés.

Avec cette requête on va récupérer pour chaque projet les données suivantes:

Traiter le dataset avec R

Marque/Hors-marque

Une fois que vous avez collecté les données pour tous vos projets, on va procéder à la 1ère catégorisation – Marque/Hors-Marque. Sans cette catégorisation les résultats de notre analyse seront fortement faussés.

Notamment on va ajouter dans chaque variable (=site) une nouvelle colonne « branded » où en face de chaque requête on affichera:

  • « branded » s’il s’agit d’une requête « marque »
  • « unbranded » s’il s’agit d’une requête « hors-marque ».

Mais avant de faire cette segmentation il faut se mettre d’accord ce qu’on comprend par une requête marque.

Marque ≠ nom de domaine

Advanced Web Ranking dans ses études du taux de clic utilise la définition suivante « A branded search is defined as having a keyword that is contained in the domain name ».

Cette méthode peut être efficace si on n’a pas les moyens de traiter les projets individuellement, un par un (comme c’est le cas de AWR). Mais son principal défaut: la marque – ce n’est pas toujours le nom de domaine:

  • française des jeux → fdj.fr
  • centre national de la recherche scientifique → cnrs.fr
  • particulier à particulier → pap.fr
  • aéroport de paris → parisaeroport.fr…

Marques avec fautes de frappe

Un autre aspect – toutes les marques ne sont pas toujours évidentes à saisir, du coup il faut prendre en compte aussi les fautes de frappes.

Il ne faut pas aller très loin pour voir des exemples: Peugeot, Leroy Merlin ou 20minutes.fr vont avoir de beaux éventails des requêtes pointant leurs pages d’accueil.

Requête « Marque » qui ne ressemble pas au nom de la marque

Et le dernier point: Qu’est-ce qu’on fait avec les expressions qui sont étroitement liées à la marque, mais qui sont loin de son appellation?

Par exemple, devons-nous considérer comme requête marque « rer a » pour le site de ratp.fr, « loto » pour fdj.fr ou « 3008 » pour peugeot.fr?

Dans le cadre de notre étude, j’entends par une requête marque celle qui correspond à une intention très forte de l’internaute de visiter un site particulier.

Est-ce que la personne qui saisit « peugeot 3008 » veut absolument passer au site officiel de Peugeot? Ce n’est pas évident. Ainsi j’ai préféré traiter ces requêtes de hors-marque.

Techniquement dans Rstudio on va utiliser la fonction grepl qui va regarder dans la colonne « query » si le mot-clé correspond à l’expression régulière dans laquelle on va scrupuleusement indiquer ce qu’il faut traiter de la marque:

#Ajouter une colonne avec les mots-clés catégorisés marque/hors-marque
site_fr$branded <- ifelse(grepl("terme1|terme2", site_fr$query), 'branded', 'unbranded')

On va refaire cette opération pour chaque variable (site).

Pourquoi ne l’applique-t-on pas au dataset avec tous les projets ensemble?

Puisque la même requête va être marque pour un site particulier et sera hors marque pour un autre: « nike » pour nike.com et pour un marketplace de mode.

Répartir en catégories/thématiques

Si vous avez beaucoup de projets cela peut être intéressant de les regrouper par thématiques pour pouvoir faire des analyses plus fines.

Pour cela on va ajouter :

  1. une nouvelle colonne « project » dans laquelle on mettra l’url de notre site (ça va être très utile quand on compilera le tout dans un seul dataset)
  2. une nouvelle colonne « category » dans laquelle on va associer une thématique à chaque projet. Pour le faire c’est toujours la même formule:
votresite_fr$project <- "Nom de domaine de votre site"
votresite_fr$category <- "Nom de catégorie"

Comme liste des catégories j’ai pris celle proposée par Google:

Liste des catégorie de l’API Natural Langage de Google

Compiler tous les projets dans un seul dataset

Maintenant on peut rassembler tous nos projets dans un seul et beau dataset qu’on va appeler get_all:

#Fusionner les variables sélectionnées dans un seul dataset
get_all <- rbind(dataset1, dataset2, dataset3)

#ou

#Fusionner TOUTES les variables dans votre environnement de travail dans un seul dataset
dfs = sapply(.GlobalEnv, is.data.frame)
get_all <- do.call(rbind, mget(names(dfs)[dfs]))


Pour analyser les taux de clics on n’a pas vraiment besoin de toutes les positions collectées par la Search Console.

Nous pouvons facilement n’en garder que les 2-3 premières pages de résultats de Google.

On peut également supprimer les requêtes qui ont fait juste 1 seule impression:

#Ne garder que les requêtes avec plus de 2 impressions et positionnées sur les 2 premières pages de Google
get_all <- subset(get_all, position<=20 & impressions >=2 & country == "fra")

Comme on va calculer les taux de clics en rapport avec la position dans les résultats de recherche ce sera plus pratique d’utiliser les nombres entiers. Pour cela ajoutons une nouvelle colonne « position_round »  et y afficheront la position arrondie:

# Ajouter une colonne avec la position arrondie
get_all$position_round <- with(get_all, round(position))

Dans notre étude nous avons analysé comment varient les taux de clics en fonction du nombre de mots dans la requête. Ajoutons encore une colonne « wordcount » dans laquelle calculons de combien de mots se compose chaque requête:

#Wordcount
get_all$wordcount <- sapply(gregexpr("\\b\\W+\\b", get_all$query, perl=TRUE), function(x) sum(x>0) ) + 1

En fonction des particularités de votre projet vous pouvez faire plein d’autres segmentations, par exemple:

Si la requête est une question?

#Créer une colonne "Questions" dans laquelle les mots-clés sont catégorisés en questions et non-questions
get_all$question <- ifelse(grepl("qui|que|comment|combien|quand|où|pourquoi|quel|c'est|quoi|est-ce", get_all$query), 'question', 'no-question')

Si la requête contient le terme « avis »?

#Avis
get_all$avis <- ifelse(grepl(" avis", get_all$query) , 'avec avis', 'sans avis')

Si la requête contient une transaction explicite?

#Transaction
get_all$transaction <- ifelse(grepl("acheter|achat|louer|location|vendre|vente|reserver|réserver|prix|tarif|pas cher", get_all$query) , 'avec transaction', 'sans transaction')

Pour conclure, comme vous voyez, les formules si-dessus sont très simples et pouvez ajouter plein d’autres segmentations propres à vos types de projets.

Calculer le CTR et visualiser les résultats!

Nous avons composé notre dataset et pouvons enfin procéder aux calculs des résultats!

Mais avant ça, on doit faire le choix entre 3 méthodes de calculs du taux de clic:

  1. CTR = clics/impressions.
  2. CTR moyen.
  3. CTR médian.

CTR clics/impressions – n’est pas pertinent

En règle générale, le taux de clic est une division du nombre de clics par celui d’impressions. Donc pour savoir le taux de clic moyen pour une position donnée on fait la somme des impressions et des clics associés à une position arrondie dans les résultats de recherche et on fait une division.

Cette méthode, malgré l’approche bien logique, s’avère inefficace, car les résultats sont fortement biaisés par les mots-clés à très fort volume d’impressions ce qui réduit à néant l’apport d’autres requêtes. Au final ça ne sert à rien d’analyser des dizaines de milliers de requêtes, car les résultats seront propres à une 100ne de requêtes qui font 2/3 du volume d’impressions.

Cette méthode donne les valeurs moyennes les plus basses.

CTR moyen ou médian?

Les 2 autres méthodes consistent à prendre les valeurs du CTR déjà proposées par Google Search Console.

L’avantage: toutes les requêtes sont réalignées au même niveau quelque soit leur volume d’impressions et de clics. On met également en avant la diversité des requêtes.

Cette méthode semble plus pertinente, mais demande 2 choses à faire:

  1. Retirer des calculs les requêtes sans (ou avec très peu) clics.
  2. Décider quelle mesure de tendance utiliser, notamment la moyenne ou la médiane.

Quand on analyse les taux de clics, pour chaque position on a des milliers (ou voire millions) de requêtes chacune avec sa valeur du CTR.

Sur le graphique ci-dessous un exemple type de la répartition des taux de clics d’un site web. La hauteur des boxplots reflète la dispersion des valeurs de CTR par position:

Dispersion du CTR par position

Comme on le voit, pour la même position les valeurs du CTR varient très fort. Pour faire face aux valeurs extrêmes, on a privilégié d’utiliser la médiane et non pas la moyenne.

La médiane est la valeur qui permet de partager une série en deux parties égales.

L’avantage de la médiane comme mesure de tendance centrale est qu’elle n’est pas influencée par les valeurs extrêmes. À l’inverse, l’inconvénient du CTR moyen est justement qu’il est souvent victime des valeurs extrêmes qui créent des distorsions majeures susceptibles de fausser l’interprétation des données.

Tableau comparatif des différentes méthodes de calcul du CTR

Différentes méthodes de calcul du CTR

Allez, on passe à notre jeu de données!

Grâce au package dplyr on peut manipuler facilement notre dataset en sélectionnant, filtrant, regroupant les données qui nous intéressent.

Par exemple le code ci-dessous va calculer les taux de clics médians des mots-clés hors-marque sur la 1ère page de Google à travers différents appareils:

#installer et activer Dplyr:
install.packages("dplyr", dependencies = TRUE)
library(dplyr)


ctr <- get_all %>%

#sélectionnez les colonnes que vous voulez utiliser: 
select(query, project, position_round, project, impressions, clicks, device, ctr, category, branded, wordcount) %>%

#filtrez les lignes en fonction des valeurs dans les colonnes: 
filter(branded == "unbranded" & position_round < 11 & clicks > 10) %>%

#regroupez les valeurs finales: 
group_by(device, position_round) %>%

#quelles opérations faire pour chaque groupe: 
summarise(sum_impressions = sum(impressions), sum_clicks = sum(clicks), ctr_median = round(median(ctr),3), ctr_median = round(mean(ctr),3))

Le résultat qui tombera dans la variable « ctr » sera le suivant:

Vous pouvez exporter ces résultats afin de les utiliser dans votre outil de visualisation préférée. Évidemment, on peut visualiser les résultats également dans Rstudio.

On va installer et activer le package Ggplot2 qui nous donnera plein de possibilités de présentation des résultats.

En voici quelques exemples:

Comment se répartissent des taux de clics par type d’appareil?

install.packages("dplyr", dependencies = TRUE)
library(dplyr)
install.packages("ggplot2", dependencies = TRUE)
library(ggplot2)
install.packages("wesanderson", dependencies = TRUE)
library(wesanderson)
require("ggrepel")

#Visualiser la répartition des taux de clic par device

ggplot(ctr, aes(position_round, ctr_median, colour = device, label = ctr_median)) + 
  geom_line(aes(position_round, ctr_median), data =  ctr, size = 1) + 
  geom_point(size = 3) + 
  scale_x_continuous(breaks = round(seq(min(1), max(10), by = 1),1)) + 
  scale_y_continuous(labels = scales::percent) +
  geom_label_repel(aes(label = ctr_median), 
                   size = 4, vjust = -2, 
                   data = subset(ctr, device == "DESKTOP")) + 
  theme_minimal() + scale_color_manual(values=wes_palette(n=3, name="Darjeeling1"))

Résultat:

CTR par device

Comment se répartissent des taux de clics pour les requêtes marque et hors-marque?

#Installer et activer les packages nécessaires

install.packages("dplyr", dependencies = TRUE)
library(dplyr)
install.packages("ggplot2", dependencies = TRUE) 
library(ggplot2) 
install.packages("wesanderson", dependencies = TRUE) 
library(wesanderson) require("ggrepel")

#Comparer la répartition des taux de clic pour les requêtes marque et hors-marque

#Créer la variable "ctr_marque_horsmarque" avec les taux de clics groupés par marque/hors-marque

ctr_marque_horsmarque <- get_all %>%
  #sélectionnez les colonnes que vous voulez utiliser: 
  select(query, project, position_round, project, impressions, clicks, device, ctr, category, branded, wordcount) %>%
  #filtrez les lignes en fonction des valeurs dans les colonnes: 
  filter(position_round < 11 & clicks > 10) %>%
  #regroupez les valeurs finales: 
  group_by(branded, position_round) %>%
  #quelles opérations faire pour chaque groupe: 
  summarise(sum_impressions = sum(impressions), sum_clicks = sum(clicks), ctr_median = round(median(ctr),3), ctr_median = round(mean(ctr),3))

#Créer le graphique sur les données de la variable "ctr_marque_horsmarque"
 
ggplot(ctr_marque_horsmarque, aes(position_round, ctr_median, colour = branded, label = ctr_median)) + 
  geom_line(aes(position_round, ctr_median), data =  ctr_marque_horsmarque, size = 1) + 
  geom_point(size = 3) + 
  scale_x_continuous(breaks = round(seq(min(1), max(10), by = 1),1)) + 
  scale_y_continuous(labels = scales::percent) +
  geom_label_repel(aes(label = ctr_median), 
                   size = 4, vjust = 2, 
                   data = subset(ctr_marque_horsmarque, branded == "unbranded")) + 
  theme_minimal() + scale_color_manual(values=wes_palette(n=3, name="Darjeeling1"))

Résultat:

ctr_par_marque_horsmarque

Vous pouvez procéder de la même manière pour analyser les taux de clics dans d’autres segments.

Conclusion

Bravo! Si vous lisez ces lignes, il y a de fortes chances que vous avez eu suffisamment de patience et de persévérance pour lire ce long billet jusqu’à la fin 🙂

Dans cet article, je tenais à expliquer les principaux points comment nous avons réalisé notre étude du taux de clics.

Mais aussi à partager les instructions step-by-step vous permettant de réaliser des analyses pareilles pour vos propres projets.

On a parcouru les étapes de collecte, de traitement et de visualisation de données dans l’environnement R qui est bien adapté pour ce genre de taches.

Bon courage dans vos analyses, si vous avez des questions ou des remarques, n’hésitez pas à les laisser dans les commentaires.

De notre côté de nouvelles études vont arriver très bientôt!

Alexis Rylko

Consultant SEO chez iProspect France.
#Google #Yandex #Datascience

1 commentaire

  • Bonjour,

    L’appel à geom_label_repel ne semble plus être présent dans le package
    could not find function « geom_label_repel »

    Une idée pour le remplacer ou le retrouver?

Auteur

Alexis Rylko

Consultant SEO chez iProspect France.
#Google #Yandex #Datascience