#SEO Créer votre maillage interne sémantique avec #R – Tutorial sur #Starwars – Partie 3


Voici mon dernier article sur la génération d’un maillage interne sémantique.
L’objectif général est de réduire le nombre de pages non crawlées et le nombre de niveaux d’arborescence.
Ainsi, on peut :
– Accroître le crawl des pages vers les pages objectifs « Star wars » précédemment sélectionnées ( Partie 2 )
– Augmenter considérablement le nombre de pages vues car les membres seront intéressés par du contenu « Star wars »
– Optimiser le champ sémantique sur lequel le site répond.

 

logo star wars

 

Episode 3 : Répartition des liens sémantiques

Objectif 1 : La priorité est de réduire la profondeur des pages objectifs, on va les placer au plus près de la page d’accueil.

Niveau BB8 :
bb8-fathead3

Pour cela, je note que j’ai plus de 110 pages en niveau 1, je vais écrire un programme en R qui permet de placer au moins deux liens sur chacune des 55 premières pages. J’ai gardé mes fichiers issus de Xenu pour montrer que l’on peut tout faire avec des outils gratuits.

library(dplyr)

#On utilise les pages supports crawlés par Xenu et on les trie en fonction de leur profondeur
DF_page_support <- read.csv("./projects/scifi-universe.com/xenu_links.txt", header=TRUE, sep = "t")

DF_page_support_select <- select(DF_page_support,Address,Type, Level,Status.Code,Size,Links.In,Links.Out) %>%
 arrange(Level) %>%
 filter( grepl('http://www.scifi-universe.com', Address), complete.cases(Level), 
 complete.cases(Status.Code), complete.cases(Size), Type == "text/html",
 #on retire les pages actualites
 !grepl('actualites/', Address) )

DF_page_support_depth <- select(DF_page_support_select,Address,Level) %>%
 mutate(url1="",url2="",url3="",url4="",url5="",
 url6="",url7="",url8="",url9="",url10="")

#on reprend les pages objectifs de l'article 2 sur le mailage interne SEO
DF_page_objectif <- read.csv("./projects/scifi-universe.com/results-page-objectifs2-anchortext.csv", header=FALSE, sep = ";")
colnames(DF_page_objectif) <- c("Pos","Url","Anchor1","Anchor2","Anchor3")
DF_page_objectif <- select(DF_page_objectif,Url,Anchor1,Anchor2,Anchor3) 

DF_merge <- merge(DF_page_objectif, DF_page_support_depth, by.x = "Url", by.y="Address") %>%
 arrange(Level)

## on va placer nos liens sur des pages de niveau 1 ou niveau 2 qui sont relativement crawlé
iter <- 1
max <- 55

for (row in 1:nrow(DF_page_support_depth)) { 
 
 DF_page_support_depth$url1[row] <- toString(DF_merge$Url[iter])
 DF_page_support_depth$url2[row] <- toString(DF_merge$Url[iter+1])
 
 iter <- iter+2;
 
 if (iter>max)
 break
}

 


 

Objectif 2 : Optimiser le champ sémantique en tenant compte de la Business Value, des volumes SEO et du glissement sémantique, …

Niveau Jedi :
jedi

On utilise un algorithme génétique , sur cette partie, il vaut être au moins niveau Jedi en langage R ! Je n’ai pas utilisé des méthodes comme le « kmeans » qui sont bien trop gourmandes en temps ou des matrices d’association qui donnent des résultats assez aléatoires.
On va donc placer chaque lien au meilleur endroit possible en fonction de plusieurs facteurs. ( Business Value, Volume SEO, Glissement Sémantique )

Le but est d’obtenir une solution approchée à un problème d’optimisation. L’algorithme génétique utilise une notion de sélection naturelle où on s’approche progressivement du résultat en  l’appliquant à une population de solutions potentielles .

img37

Avant d’utiliser cet algorithme, je récupère avec Google Planner l’ensemble des volumes SEO des pages objectifs sur les ancres définies avec Visiblis.

Je vous donne le code pour vous montrer qu’en R, il est très rapide de passer d’un tableau à trois colonnes sur un tableau à 1 colonne en ajoutant le mot clés « star wars »

AVANT

Screen Shot 01-05-16 at 11.24 PM

APRES

Screen Shot 01-05-16 at 11.25 PM

7 lignes de code ( 40 s )

result_all <- read.csv("./projects/scifi-universe.com/results-page-objectifs2-anchortext.csv", header=FALSE, sep = ";")
colnames(result_all) <- c("Pos","Url","Anchor1","Anchor2","Anchor3")
DF_SEO <- union(result_all$Anchor1,result_all$Anchor2)
DF_SEO <- as.data.frame(union(DF_SEO,result_all$Anchor3))
colnames(DF_SEO) <- c('query')
DF_SEO <- mutate(DF_SEO,query=paste('star wars ',query,sep=""))
write.csv(DF_SEO,"./projects/scifi-universe.com/keyword_for_googleplanner.csv")

Copiez le tout dans Google Planner et exporter les résultats en CSV

Screen Shot 01-05-16 at 11.31 PM

Vous obtenez ce type de fichier CSV

google planner

Ensuite, je vous conseille d’attribuer une priorité ( Business Value ) sur chacun des mots clés, en effet vous ne pouvez pas baser votre maillage interne uniquement sur des volumes SEO mais sur votre expertise et donc vos règles métiers.

Dans le cas de « Star Wars », il faut se concentrer sur les jeux récents et les films récents. Pour mon algorithme, si je met une business value au niveau 10, cela lui donne le niveau le plus important sur mon échelle.

Ensuite pour mes 111 pages objectifs, j’ai plus de 220 000 pages supports.
J’ai imaginé un bloc qui va contenir dix liens, on doit donc répartir 111 pages objectifs parmi 2 220 000 emplacements.

Il va être judicieux de placer au maximum 10 000 liens vers une page objectif.  Il est important de fixer des seuils sinon c’est toujours les mêmes liens qui vont se retrouver sur toutes les pages. Le seuil sera défini en fonction du score de la page car toutes les pages n’ont pas besoin du même nombre de liens entrants.

Les pages de priorité 10 avec des volumes SEO fort auront donc une forte probabilité d’avoir au moins 10 000 liens sur des pages fortement crawlés.

L’objectif principal est de permettre aux internautes de découvrir du contenu cohérent avec leurs recherches.

Voici donc une version simplifiée de mon algorithme génétique car il ne serait pas judicieux de vous noyer dans le code. Si on fait l’abstraction au langage R, il faut tout simplement définir la formule mathématique qui va sélectionner la meilleure population qui répond à notre problème.

Souvent, on peut tenir compte du nombre de mot clé en commun pour placer les liens les plus pertinents, mais sur ce site de science fiction le contenu « Star Wars » est pertinent sur toutes les pages et « Star Wars » sera très tendance sur les prochains mois voire les prochaines années. Je ne vais pas donner ma version qui tient compte du glissement sémantique et qui permet sur des sites plus généralistes de placer de garder des liens complètement cohérents avec la page analysée.

Le but est donc de mettre en avant les pages objectifs en fonction d’une note de 1 à 10 qui correspond à la Business Value où l’intérêt de la page et le volume SEO de la requête associée.

J’ai choisir de normaliser les deux valeurs sur une échelle de 1 à 1000 et de répartir le poids sur du 50-50 mais libre à vous d’optimiser la formule en fonction du site, des concurrents et de sa thématique.

normaliser

La fonction écrite en R :

normalit<-function(d){
max <- max(d)
min <- min(d)
return(round((((d - min)/(max-min))*1000),0))
}

La fonction qui va aider à faire le choix dans l’algorithme génétique fait la somme de ses facteurs et contrôle qu’il y a bien un nombre de liens limité à 10 par page.

normalize

J’ai créé un petit exemple où pour chaque page support, je place de 1 à 3 liens parmi les 10 pages objectifs et on se limite à une fréquence de 5 par page objectif.

library(genalg)
library(dplyr)

#chargement des pages support
page_support <- read.csv("./projects/scifi-universe.com/page-support.csv", header=TRUE, sep=";")
colnames(page_support) <- c("Corpus","Url","Session","Level","Links.Out","Links.In","Status.Code","Size")
page_support = filter(page_support,!grepl("actualite",Url))

#nombres de liens
max_links <- 3
#nombre de pages support
max_page_support <- 10
#augmenter votre population pour avoir des résulats pertinents
#à vous de determiner le ration entre la précision des résultats et la rapidité du calcul
max_population <- max_page_support * 10
cat('population ',max_population,'n')

#jeu de test
dataset <- data.frame(item = c("url_objectif_1", "url_objectif_2", "url_objectif_3", "url_objectif_4",
 "url_objectif_5", "url_objectif_6", "url_objectif_7", "url_objectif_8",
 "url_objectif_9", "url_objectif_10"
 ),
 volume_seo = c(1000, 5000, 150, 200, 3000, 1000, 3000, 100, 90, 300),
 # priority : high -> 10 : low -> 1
 priority = c(1, 5, 10, 2, 3, 4, 5, 6, 10, 2),
 weight = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
 #corpus =c(0,0,0,0,0,0,0,0,0,0),
 max = c(5,5,5,5,5,5,5,5,5,5))

#fonction qui évalue la pertinence de chaque proposition
evalFunc <- function(x) {
 current_volume_seo <- x %*% dataset$volume_seo
 current_priority <- x %*% dataset$priority
 current_weight <- x %*% dataset$weight
 # on accorde la même importance au volume seo et à la business value
 current_importance <- current_volume_seo + current_priority
 # si un resultat contient plus de liens que notre maximum de liens dans le bloc, on le retire
 if (current_weight > weightlimit) 
 return(0) 
 else 
 return(-current_importance) 
}

#normalize : retourne une valeur entre 0 et 1000
normalit<-function(d){
 max <- max(d)
 min <- min(d)
 return(round((((d - min)/(max-min))*1000),0))
}

#on normalise les facteurs entre 0 et 1000
dataset$volume_seo <- normalit(dataset$volume_seo)
dataset$priority <- normalit(dataset$priority)

for (j in 1:nrow(page_support)) { 
 #cat(toString(page_support$Url[j]),"n")
 GAmodel <- rbga.bin(size = max_page_support, popSize = max_population, iters = 100, mutationChance = 0.01, 
 elitism = T, evalFunc = evalFunc)
 #result
 cat('sol ',GAmodel$population[max_population,],'n')
 solution <- GAmodel$population[max_population,]
 
 # une fois la solution trouvé, on met à jour le dataframe en réduisant le seuil des liens choisis
 dataset$max = dataset$max - solution
 #si un seuil est atteint, on ne peut plus placer le lien
 #on augmente le poids du lien ou on degrade sa note
 idx <- which(dataset$max<=0) 
 if (length(idx)>0) {
 #dataset[idx,]$weight <- weightlimit
 dataset[idx,]$volume_seo <- 0
 dataset[idx,]$priority <- 10
 }
 cat('max ',dataset$max,'n')
 #si il reste autant de liens que de liens autorisés, on arrete le calcul
 #l'algo sera moins fiable en fin de calcul mais cela est peu important car plus de 90% des liens sont placés
 #on peut se contenter de les mettre au fur et à mesure sur les positions restantes
 if (length(which(dataset$max>0)) - max_links <= 0 ) {
 print('valeur limite atteinte')
 break;
 } 
}

Voici le résultat de ce petit exemple,
 Screen Shot 01-07-16 at 11.49 PM

Choix des ancres et Mise à jour
Pour chacune des pages support, on va choisir une ancre sémantique.
Là dessus, j’ai créé une fonction R qui va choisir l’ancre la plus adaptée à la thématique de la page.
Je vous laisse le soin de développer votre propre fonction. Les ancres se basent déjà sur un corpus « Star Wars » donc elle répondent très bien à votre page objectif.
Pour la mise à jour, il faut refaire le calcul régulièrement car les pages supports les plus crawlées vont fortement évoluer et un corpus d’actualité va changer très régulièrement.

Là on suit les derniers conseils du Maitre Yoda :

  • Le même nombre de pages support, tu garderas
  • La profondeur, tu mettras à jour
  • Les ancres sémantiques, tu conserveras
  • Visiblis, tu utiliseras
  • Les nouvelles pages objectifs « Star Wars », tu ajouteras
  • L’algorithme génétique, tu relanceras

Conclusion
J’espère que cet article n’est pas trop compliqué mais désormais le SEO fait appel à de nombreux domaines : Mathématiques, Statistiques, Algorithmie, Sémantique…

J’ai généré un fichier plat contenant les ancres et les liens à placer sur chacune des pages supports et dès que ça sera implémenté par le Webmaster, on suivra les évolutions. Durant l’écriture des ces trois articles, il a déjà corrigé de nombreux soucis qui remontaient à chaque crawl ( Title non uniques, H1 dupliqué, Pagination infinie, Page 404 qui répond en 200, … )

Sinon, j’ai travaillé avec R mon langage de prédilection mais utilisez la technologie avec laquelle vous êtes le plus à l’aise.
Bien sûr, ces liens peuvent être mis en avant en travaillant un peu le design du bloc html qui va les accueillir.
L’objectif principal est de fournir un contenu cohérent à vos internautes.

Pour suivre l’impact de ce maillage, suivez les indicateurs suivants :

  • Nombre de pages supports
  • Nombres de pages objectifs
  • Corpus utilisé ( 1-gram, 2-gram, 3-gram de Visiblis )
  • Profondeur des pages objectifs avant et après
  • Part du crawl sur les pages Star Wars avant et après
  • Trafic SEO sur ces pages avec Google Analytics
  • Position dans les SERP avec SemRush ou le nouveau Serposcope

Remerciements
Un grand merci à mes trois relecteurs préférés et un grand merci à tous mes lecteurs qui partagent sur les réseaux sociaux.

Merci aussi à Jérôme Rossignol qui a énormément simplifié l’analyse sémantique grâce à son outil Visiblis : http://www.visiblis.com/

Vous pouvez me retrouver au prochain SEOCamp de Lille mais aussi à QueDuWeb qui aura lieu à Deauville cette année, le sujet abordé sera l’utilisation du R pour le SEO
https://deauville.queduweb.fr/

Si vous souhaitez découvrir une autre méthode, je vous invite à lire les 3 articles de Grégory Florin :
http://gameofseo.fr/2016/01/creer-un-outil-de-maillage-interne-la-generation-des-liens-33/

Nous avons prévu de donner un podcast spécial sur le Maillage Interne ( surement le 18 Janvier )  où nous allons discuter de nos différentes méthodes.
http://www.moise-le-geek.fr/category/podcast/

logo star wars

Que la force soit avec vous !

Crédits photo : Starwars

Laisser un commentaire

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