Recherche de facteurs SEO avec le Machine Learning (partie 1)

Quels sont les facteurs SEO qui permettent de positionner une page de son site sur la première page de résultats de Google ?

Voici la question à 1 million de US$ que se posent tous les possesseurs de sites depuis maintenant près de 20 ans !!!

Jusqu’à récemment, la réponse se faisait de façon plutôt empirique à partir d’avis et d’expériences d’experts du référencement, d’informations au compte goutte du fameux Matt Cutts de Google ou de fournisseurs de données et d’outils SEO comme MOZ, Majestic SEO, Ahrefs, SEMrush, Yooda …

Aujourd’hui, la communauté SEO commence à s’intéresser à ce que l’on a appelle le « Data SEO » c’est à dire l’utilisation des techniques des Data Sciences au service du SEO.

Dans cet exercice (en 3 parties) nous allons vous proposer de rechercher, à partir de données récoltées sur le Web ou bien crawlées, des facteurs SEO importants à partir d’algorithmes de Machine Learning.

Pour cela il nous faut en premier lieu un fichier comportant des informations de positionnement d’une page en fonction d’un mot-clé. En d’autres termes un fichier qui nous donne :

  • La position d’une page pour un mot clé donné dans les résultats de Google
  • Le mot clé pour laquelle cette page est positionnée
  • L’url de la page

On trouve ces informations par exemple chez SEMrush ou chez Yooda pour les mots clés en Français.

Ensuite, il faut pouvoir enrichir ces informations avec tout ce que l’on pourra récupérer en crawlant les pages ou à partir d’API de fournisseurs de données.

L’idéal serait de pouvoir récupérer des informations concernant la page elle-même (https, mot clé dans les titres), la page dans son site (profondeur, page rank interne…), les liens externes vers la page (avec une notion de qualité) … Mais bon cela vous obligerait à avoir plusieurs abonnements payants

API Yooda Insight

Pour cette exercice nous utiliserons comme source de positionnements l’API de Yooda actuellement en bêta test et que nous avions présentée dans un article précédent : Test de l’API Insight de Yooda avec le logiciel R

Si vous souhaitez aussi tester l’API Insight, et reproduire entièrement ce test, demandez un accès à Yooda sur cette page : Accès API en Bêta Gratuite.

Logiciel R

Comme dans nos articles précédents nous vous invitons à téléchargez Le Logiciel R sur ce site https://cran.r-project.org/, ainsi que l’environnement de développement RStudio ici : https://www.rstudio.com/products/rstudio/download/, afin de pouvoir tester vous même le code source.

Test avec R

Ce test sera divisé en 3 parties. Dans cet article nous testerons les informations que nous pouvons créer à partir des urls et des noms de domaines. Dans un prochain article nous utiliserons un crawler pour récupérer des données « techniques » sur les pages, et enfin dans un dernier article nous créerons des données mots-clés vs pages en fonction du contenu des pages.

Pour illustrer le propos nous avons décidé de nous intéresser au secteur des « cosmétiques bio ». Il nous fallait donc des pages de sites qui étaient dans la base de Yooda. Comme l’API ne fournit pas pour l’instant de liste de sites à partir de mots-clés, nous avons été directement rechercher les « Leaders » de la thématique « cosmétiques bio » sur l’interface Web.

Recherche Leaders Yooda

Yooda vous fournit une liste de site leaders dans la thématique dont vous pouvez recopier les domaines :

Résultats Recherche Leaders Yooda

Même si vous n’avez pas de compte Premium, vous pouvez rapidement récupérer une liste de sites, par exemple en faisant varier les mots clés (mais toujours dans la thématique). Je suggère d’éviter de garder des sites généralistes comme Youtube, FaceBook ou encore Wikipedia et qui ne nous intéressent pas dans cet exercice.

Voici le fichier d’une cinquantaine de domaines que j’ai créé dans cette thématique : domains.csv

Code Source R

Vous pouvez copier/coller les morceaux de code source dans un script R pour les tester.

Bibliothèques utiles

Chargement des bibliothèques utilisées dans cette première partie. Si c’est la première fois que vous chargez ces bibliothèques vous devez au préalable installer les « packages ».

API Yooda Insight

Vous devez indiquer ici votre clé d’API. on en profite pour vérifier nos crédits. De mémoire au départ nous en avons 10 millions il me semble.

Récupération des données de positionnement avec l’API Yooda Insight

Attention l’application mange beaucoup de crédits : 2 millions pour 200.000 enregistrements récupérés sur un total de 10 millions qui vous sont alloués au départ. Il faudra donc éviter de lancer le processus complet plusieurs fois.

Le processus se fait à partir du fichier de domaines que nous avions préalablement établi. Celui-ci doit se trouver dans le répertoire courant de votre script R. Pour éviter de tout perdre en cas de plantage nous sauvegardons au fur et à mesure les fichiers de positionnements par domaine dans un sous répertoires « Yooda ».

Regroupement des fichiers de domaines

Dans cette partie nous regroupons tous les fichiers de positionnements par domaine dans un seul jeu de données.

Variables à expliquer

Normalement la variable « position » est la variable à expliquer en fonction des autres données. Ici les données ne nous donnent que des positions de 1 à 13 dans les résultats de Google. Il aurait été intéressant d’avoir des observations de pages / mots clés moins bien positionnées pour mesurer des « mauvaises » pages.

Comme il nous semble très optimiste de déterminer un modèle permettant de classer les pages sur 13 positions, nous créons 2 variables booléennes, une indiquant la première place ou non, l’autre les 3 premières places ou non.

Ajouts de variables explicatives – facteurs SEO

Nous allons ajouter des variables potentiellement explicatives à notre jeu de données :

  • kwindomain : compte l’occurence du mot clé dans le domaine.
  • kwinurl : compte l’occurence du mot clé dans le reste de l’url.
  • ishttps : est-ce une url en https ?
  • isSSLEV : le SSL est-il de type Extended Value ?
  • urlnchar : nombre de caractères dans l’url.
  • urlslashcount : nombre de / dans l’url (pseudo « level »)

Ce sont parmi ces variables explicatives potentielles que l’on doit trouver nos facteurs SEO.

La structure du jeu de données « AllDataKeywords » est la suivante :

> str(AllDataKeywords)
‘data.frame’: 154979 obs. of 21 variables:
$ domain : Factor w/ 54 levels « 1001pharmacies.com »,..: 1 1 1 1 1 1 1 1 1 1 …
$ obs_domain_id : int 1 2 3 4 5 6 7 8 9 10 …
$ domain_id : int 10053420 10053420 10053420 10053420 10053420 10053420 10053420 10053420 10053420 10053420 …
$ url : Factor w/ 49240 levels « https://www.1001pharmacies.com/ »,..: 1 1 1 160 1 1060 261 1 1398 503 …
$ position : int 1 5 1 2 8 1 3 7 3 1 …
$ score : int 997280 907500 544640 417060 307700 298080 254740 229900 208680 198720 …
$ traffic : int 9973 9075 5446 4171 3077 2981 2547 2299 2087 1987 …
$ keyword.kw_id : int 82195312 1306832 70497009 56197 9276 132043117 3690926 7718477 7726273 3221817 …
$ keyword.keyword : Factor w/ 129660 levels « 100 pharmacie »,..: 12 3527 16 328 3428 641 528 3543 4053 1614 …
$ keyword.search_volume: int 27100 165000 14800 33100 90500 8100 27100 60500 22200 5400 …
$ keyword.competition : num 0.07 0.03 0.07 0.18 0.67 0.65 0.41 0.71 0.99 1 …
$ keyword.cpc : num 0.53 0.34 0.23 0.31 0.56 0.86 0.13 0.41 0.31 0.29 …
$ keyword.results_nb : num 447000 73300000 177000 16500000 9770000 799000 15400000 23300000 1790000 1160000 …
$ istop1pos : logi TRUE FALSE TRUE FALSE FALSE TRUE …
$ istop3pos : logi TRUE FALSE TRUE TRUE FALSE TRUE …
$ kwindomain : int 0 1 1 0 0 0 0 0 0 0 …
$ kwinurl : int 0 0 0 1 0 1 1 0 1 0 …
$ ishttps : num 1 1 1 1 1 1 1 1 1 1 …
$ isSSLEV : num 1 1 1 1 1 1 1 1 1 1 …
$ urlnchar : int 31 31 31 40 31 109 43 31 47 48 …
$ urlslashcount : int 3 3 3 3 3 3 3 3 3 3 …
>

Nous avons aussi sauvegardé le jeu de données dans un fichier .csv. Vous pouvez le récupérer sur notre compte GitHub sous forme de fichier compressé .zip : AllDataKeywords.zip

Machine Learning : Préparation des données.

Dans cette partie nous allons récupérer les données sauvegardées préalablement, sélectionner la variable à expliquer (ici istop3pos) et les variables explicatives (facteurs SEO potentiels ?) puis créer un jeu de données d’entrainement et un jeu de données de test dont nous aurons besoin pour tester les modèles.

Modèle Régression Logistique

Dans ce premier test nous allons tester un algorithme de régression logistique. pour ceux qui souhaitent allez plus loin dans la compréhension du modèle vous pouvez trouver ici : un cours sur la Régression Logistique pour l’apprentissage supervisé de l’université de Lyon.

Bon, pour ceux qui ne souhaitent pas entrer dans les détails, ne vous inquiétez pas, le processus est toujours plus ou moins le même :

  • Je divise mon jeu de données de base en 2 paquets : les données d’entrainement et les données de test.
  • Je crée un modèle à partir d’un algorithme et de données d’entrainement.
  • je crée des prédictions à partir du modèle et des données de test.
  • Je compare les prédictions aux vraies données contenues dans le jeu de test.

La matrice de confusion et le calcul de la moyenne des « bonnes » prédictions permet de déterminer la qualité du modèle :

> (ConfusionPerCent <- round(prop.table(Confusion), 4)) pred.glmmod.logi 0 1 0 0.2280 0.2001 1 0.2540 0.3180 > mean(pred.glmmod.logi == as.numeric(test$istop3pos))
[1] 0.5459414

Le modèle est parfait si la moyenne trouvée est de 1 et il ne fait pas mieux que le hasard si celle-ci est proche de 0.5. ici nous trouvons 0.5459414 ce qui n’est pas terrible.

La courbe ROC (Receiver Operating Characteristic = caractéristique de fonctionnement du récepteur) et le calcul de l’AUC (Area Under the curve) permettent aussi d’évaluer le modèle :
ROC AUC Régression Logistique
AUC = 0.5725 … bon ce n’est pas terrible.

Importance des variables :

> varImp(glmmod)
Overall
kwindomain 4.370518
kwinurl 11.435329
ishttps 22.949776
isSSLEV 31.505129
urlnchar 18.391328
urlslashcount 30.126572
>

Ici, La variable « isSSLEV » indiquant les SSL en Extended Value est celle qui contribue le plus au modèle, la variable « urlsslashcount », qui représente un pseudo « niveau de page interne » dans un site, arrive en second. Toutefois comme le modèle est relativement proche de 0.5 on ne peut pas dire qu’il soit franchement valide.

Modèle Naïve Bayes

Essayons un autre modèle. Le modèle Naïf Bayésien est un classifieur basé sur le théorème de Bayes :
Téorème de Bayes
Pour en savoir plus, reportez vous à la notice Wikipedia : Classification Naïve Bayésienne.

Le Modèle Naïve Bayes ne nous apporte pas grand chose dans notre cas. Il fonctionne même moins bien que le Modèle par Régression Logistique précédent.

ROC AUC Naïve Bayes

Modèle Random Forest avec randomForest

A ma connaissance, il existe 2 bibliothèques pour créer un modèle de « Forêt Aléatoire » dans R : randomForest et ranger. Ici nous utilisons randomForest.

Vous trouverez ici une explication claire de ce que sont les forêts aléatoires, sur le blog de Lise Vaudor. Avec un autre exemple en R.

Le modèle est un peu mieux que celui de Régression Linéaire :
ROC AUC Random Forest randomForest

Importance des variables :

> rfmod$importance
FALSE TRUE MeanDecreaseAccuracy MeanDecreaseGini
kwindomain 0.0000647654 0.0001903043 0.0001297618 10.13511
kwinurl 0.0046686792 0.0008444315 0.0026880590 67.93826
ishttps 0.0009180974 0.0346657656 0.0183843055 271.63407
isSSLEV 0.0099572023 0.0394399284 0.0252218318 353.54207
urlnchar 0.0088439978 0.0308398632 0.0202375132 659.55647
urlslashcount 0.0311110665 0.0321996717 0.0316769276 1101.59703
>

Ce n’est pas très lisible mais il faut lire les nombres à droite correspondants à la valeur de « MeanDecreaseGini ». Dans ce cas la variable la plus importante est « urlslashcount ».

Modèle Random Forest avec ranger

ranger est une autre bibliothèque permettant de créer un modèle Random Forest.

Le modèle créé par ranger est quasi le même que celui créé par randomForest :
ROC AUC Random Forest ranger

Modèle XGBoost

XGBoost pour eXtreme Gradient Boosting. XGBoost est un modèle assez récent (2014) basé sur un algorithme de gradient boosting. Cet outil est devenu rapidement très populaire chez les Data Scientists car il donne des résultats souvent meilleurs que des outils plus anciens comme par exemple le Random Forest.

Pour ceux qui souhaitent approfondir le sujet vous trouverez ici un cours de l’université de Toulouse qui discute des différents modèles et aborde le modèle Gradient Boosting (un peu ardu !).

Pour les autres, on se contentera d’utiliser la bibliothèque 🙂 :

Le modèle XGBoost donne des résultats meilleurs que les modèles précédents avec une AUC de 0.661
ROC AUC XGBoost

La variable la plus importante est ici le nombre de caractères dans l’url « urlnchar_clean » (regardez l’indicateur « Gain ») :

> (importance <- xgb.importance(feature_names = colnames(x = train.treat), model = xgbmod)) Feature Gain Cover Frequency 1: urlnchar_clean 0.410036436 0.73081319 0.581213971 2: urlslashcount_clean 0.366750031 0.12605521 0.216344524 3: ishttps_clean 0.118527197 0.04053112 0.090200068 4: isSSLEV_clean 0.065902531 0.03964566 0.045100034 5: kwinurl_clean 0.035875160 0.03383810 0.061037640 6: kwindomain_clean 0.002908645 0.02911672 0.006103764 >

Conclusion

A ce stade nous n’avons malheureusement pas trouvé un modèle suffisamment valide permettant de trouver des facteurs SEO intéressants.

Dans l’article suivant de cette série, nous enrichissons les données avec des données techniques des pages.

N’hésitez pas à faire vos remarques et suggestions dans les commentaires.

Merci de votre attention,

Pierre

Laisser un commentaire

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

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.