Suivre ses positions à l’ancienne

Suivre ses positions à l’ancienne

Aujourd’hui, il y a pléthore d’outils pour vous permettre de suivre vos positions. Sans entrer dans le détail entre ceux qui proposent un split Desktop / Mobile, le suivi des positions 0, etc. je vous propose de relever vos positions à l’ancienne. Non par flegme mais simplement parce que certains cas de figure imposent encore de revenir à nos bonnes vieilles méthodes.

Pas de langage R ni de Python ni encore de Machine learning mais simplement un fichier Google Sheets (et un Data Studio pour les plus téméraires).

Suivre ses positions à la volée

Partons du principe que nous souhaitons suivre les positions pour un domaine en particulier et pour certains mots-clés spécifiques. Nous allons relever :

– La position actuelle.
– La page positionnée.
– La page qui occupe la première place sur le SERP.
– La page positionnée juste devant nous.
– La page positionnée juste derrière nous.
– Le title et la meta description (parce qu’on est des caïds).

Si vous avez un accès SemRush, alors vous pouvez indiquer votre clé d’API dans l’onglet Settings et cliquer sur « Yes » en B2 pour récupérer les volumes de recherche mensuels moyens.

Via Outils > Editeur de scripts, nous pouvons analyser les scripts suivants :

– Google Tricks : ici, on configure toute la magie pour récupérer les données évoquées précédemment.

// -----------------------
// RankTank Google Tricks. 
// -----------------------

/* DEFAULTS */
function presets() {
  
  var MAX_RETRIES = 5; // Number of times to try Google before failing
   
  return {maxRetries:MAX_RETRIES};
  
}

/* DELAY FETCHURL TO RESPECT QUOTAS */
function delayFetch() {
  var milliseconds = Math.floor(((Math.random() * 50) + 25) * 10) // Delay 250-500ms
  
  Utilities.sleep(milliseconds)
}

function getRank(keyword,lang,loc,userDomain) {
  if(!keyword)return null;
  var urls=[],resultLine=[],
      resultURL,resultDomain,title="",meta="",splitURL,ranked=null,
      RETRIES=5;
  
  // Begin locale hack 1 November 2017
  var g_loc=loc.slice(-2,loc.length);
  
  if(loc=="google.com") {
    g_loc="us";
  }
  
  // var url='https://www.'+loc+'/search?q='+encodeURIComponent(keyword)+'&fp=1&dpr=2&sns=1&pf=p&tch=1&num=100&rl=lang_'+lang+'&hl='+lang;
  var url='https://www.'+loc+'/search?q='+encodeURIComponent(keyword)+'&gl='+g_loc+'&fp=1&dpr=2&sns=1&pf=p&tch=1&num=100&rl=lang_'+lang+'&hl='+lang;
  // End local fix
  
  //Strip www from userDomain
  splitURL=userDomain.split(".");
  if(splitURL[0]=="www")splitURL.shift();
  userDomain=splitURL.join(".");
  
  try {
    var serp=UrlFetchApp.fetch(url,{muteHttpExceptions:true,method:"GET",followRedirects:true});
    var result=serp.getContentText().split('/*""*/');
    var searchResults=JSON.parse(result[3]);
    var serpResults=searchResults.d.split('<h3 class="r"><a href="/url?q=');
    
    // Let's try Google again as the API tricks us
    var block=4
    while(serpResults[1] == null && block<9) {
      block++
      searchResults=JSON.parse(result[block]);
      serpResults=searchResults.d.split('<h3 class="r"><a href="/url?q=');
    }
    
    // If we still don't have a result we'll assume quota reached
    if(serpResults[1] == null){
      //console.log({Message: "Empty Check", initialData: serpResults[0]});
      resultLine.push(["-","Google Apps (Quota Exceeded)",null,null,null,null,null]);
      return resultLine; 
    } else {
      for(var i=1;i<serpResults.length;i++) {
        // Get URL
        resultURL=decodeURIComponent(serpResults[i].split('&amp;sa=U')[0]);
        resultDomain=resultURL.split("://")[1];
        if(resultDomain.indexOf("/")!==-1)resultDomain=resultDomain.split("/")[0];
        splitURL=resultDomain.split(".");
        
        //Strip www from resultDomain
        //if(splitURL.length>2)splitURL.shift();
        if(splitURL[0]=="www")splitURL.shift();
        resultDomain=splitURL.join(".");
        
        urls.push(resultURL);
        
        if(userDomain==resultDomain&&!ranked) {
          ranked=i;
          //Get title
          title='<'+serpResults[i].split('</h3')[0];
          //Get meta
          meta=serpResults[i].split('<span class="st">')[1].split('</span><br></div>')[0].split('</span></td>')[0]; 
        }
      }
      
      if(urls[0]) {
        //console.log(serpResults[1]);
        resultLine.push([ranked||"-",urls[ranked-1]||"Not ranked",urls[ranked-2]||null,urls[ranked]||null,urls[0],title.stripTags(),meta.stripTags()]);
        return resultLine;
      } else {
        //console.log({Message: "Broken", initialData: serpResults[1]});
        resultLine.push([ranked||"-",urls[ranked-1]||"No response",urls[ranked-2]||null,urls[ranked]||null,urls[0],title.stripTags(),meta.stripTags()]);
        return resultLine;
      }
      
    } 
  } catch(e) { 
    return JSON.stringify(e); 
  }
}

String.prototype.stripTags = function() {
  var s=this.replace(/(<\/span><br>)/g, "\n");
  return s.replace(/<[^>]+>/igm, '').replace(/&#39;/igm,"'").replace(/&nbsp;/igm," ").replace(/&amp;/igm,"&").replace(/&quot;/igm,'"');
}

– Sheet Interface : dès lors que vous allez ajouter ou supprimer un domaine ainsi que des mots-clés, les résultats se mettront directement à jour.

/* Interface between sheet and RankTank_GoogleTricks.gs */

function onEdit(e) {
  return null
  
  var newKeyword,i=0;
  
  var FUNCTION_SHEET="internalFunctions";
  var MAIN_SHEET="Position Tracker";
  var OUTPUT_SHEET_FIRST_RANGE="E11:N11";
  var OUTPUT_SHEET_FIRST_CELL="E12";
  var COL_KEYWORDS=3; //Column with keywords
  var ROW_KEYWORDS=11; //First row with keywords in
  var DEBUG_CELL="C8";
  var DOMAIN_CELL="C6";
  var LANG_CELL="B9";
  var LOC_CELL="B6";
    
  var sheet=e||SpreadsheetApp.getActive();
  var src=sheet.source||sheet.getSheetByName(MAIN_SHEET);
    
  var mainSheet=e.source.getActiveSheet();
  var functionSheet=e.source.getSheetByName(FUNCTION_SHEET);
  if(mainSheet.getName() !== MAIN_SHEET) return null; //We only want to watch the main sheet
 
  //if(functionSheet.getActiveCell().getValue()=="") return null;
  
  var debugCell=mainSheet.getRange(DEBUG_CELL).clearContent();
  var domain=mainSheet.getRange(DOMAIN_CELL).getValue();
  var lang=functionSheet.getRange(LANG_CELL).getValue();
  var loc=functionSheet.getRange(LOC_CELL).getValue();
    
  var input={cell:mainSheet.getActiveCell(),
             col:mainSheet.getActiveCell().getColumn(),
             row:mainSheet.getActiveCell().getRow(),
             value:mainSheet.getActiveCell().getValue()};
    
  if(input.col===COL_KEYWORDS && input.row>=ROW_KEYWORDS) {
    //User added new keyword
    //var userResultRange=input.cell.offset(0,2);
    var commandCell=functionSheet.getRange("D3").offset(input.row-11,0);
    //var resultCell=commandCell.offset(0, 1);
    //var resultRange=commandCell.offset(0, 2);
    var currResult=resultCell.getValue();
    
    var functionSheetRank=functionSheet.getRange(input.row-8,5);
    var functionSheetURL=functionSheet.getRange(input.row-8,6);
    var functionSheetAbove=functionSheet.getRange(input.row-8,7);
    var functionSheetBelow=functionSheet.getRange(input.row-8,8);
    var functionSheetTitle=functionSheet.getRange(input.row-8,9);
    var functionSheetDesc=functionSheet.getRange(input.row-8,10);
    
    var displaySheetRank=mainSheet.getRange(input.row,input.col+2).clearContent();
    var displaySheetURL=mainSheet.getRange(input.row,input.col+3).clearContent();
    var displaySheetAbove=mainSheet.getRange(input.row,input.col+7).clearContent();
    var displaySheetBelow=mainSheet.getRange(input.row,input.col+8).clearContent();
    var displaySheetTitle=mainSheet.getRange(input.row,input.col+9).clearContent();
    var displaySheetDesc=mainSheet.getRange(input.row,input.col+10).clearContent();
    
    if(input.value==="") {
      //Keyword was removed. clear values
      commandCell.clearContent();
      functionSheetRank.clearContent();
      functionSheetURL.clearContent();
      functionSheetAbove.clearContent();
      functionSheetBelow.clearContent();
      functionSheetTitle.clearContent();
      functionSheetDesc.clearContent();
      return null;
    }
    
    debugCell.setValue("Getting rank for '"+input.value+"' on "+domain+" for "+loc+" in "+lang);
    commandCell.setValue("fetch"); //Formula watches for this
    displaySheetRank.setValue("Starting...");
    var i=0;
    while(resultCell.getValue()=="") {
      i++;
      //userResultRange.setValue("Working ("+i+")");
    }
    
    functionSheetRank.copyTo(displaySheetRank, {contentsOnly:true});
    functionSheetURL.copyTo(displaySheetURL, {contentsOnly:true});
    functionSheetAbove.copyTo(displaySheetAbove, {contentsOnly:true});
    functionSheetBelow.copyTo(displaySheetBelow, {contentsOnly:true});
    functionSheetTitle.copyTo(displaySheetTitle, {contentsOnly:true});
    functionSheetDesc.copyTo(displaySheetDesc, {contentsOnly:true});
    
    commandCell.setValue("done");
    
    debugCell.clearContent();
    
  }
  
  return null;

}

– Internal Functions : si l’outil est mis à jour, vous pourrez en être notifié. Ce script permet également de requêter l’API SemRush une fois que vous avez ajouté votre API Key dans l’onglet Settings.

function checkForUpdate(toolCode, currentVersion) {
  currentVersion=parseInt(currentVersion);
  var updateInformation;
  var updateURL="https://spreadsheets.google.com/feeds/list/1QBKbhx47fK9bAlRMd9Qmi01kBoeaFHvZQevFuRF4nKA/od6/public/values?alt=json&single=true";
  var updateDataRaw = UrlFetchApp.fetch(updateURL, {muteHttpExceptions: true }); //Get info from the Google Sheet update server
  var updateData=JSON.parse(updateDataRaw);
  for(var i=0;i<updateData.feed.entry.length;i++) { if(updateData.feed.entry[i].gsx$code.$t==toolCode) { //Logger.log(updateData.feed.entry[i].gsx$code.$t); var updateVersion=parseInt(updateData.feed.entry[i].gsx$version.$t), updateLink=updateData.feed.entry[i].gsx$updatelink.$t, updateNotes=updateData.feed.entry[i].gsx$whatsnew.$t var updateMessage=(updateVersion>currentVersion) ?
        "VERSION "+currentVersion+"\n\n*** UPDATE ***\nCLICK HERE\nVERSION "+updateVersion :
        "VERSION "+currentVersion+"\n\nUp to date!";
      var updateIcon=(updateVersion>currentVersion) ? "❌" : "✅";
      updateInformation=[updateMessage,updateIcon,updateVersion]; //updateLink,updateNotes
    }
  }
  return updateInformation;
}

function getSEMrushKeywordData(query,db,apiKey) { 
  var apiUrl="http://api.semrush.com/?type=phrase_this&key="+apiKey+"&export_columns=Nq&phrase="+query+"&database="+db;
  var result= UrlFetchApp.fetch(apiUrl,{"muteHttpExceptions":true}).getContentText().split(/\r?\n/);
  return (result.length>1)?result[1]:"-";
}

Notez qu’ils appartiennent à Jaco van Wik de Rank Tank, je n’ai fait qu’ajouter ce qui figure dans la suite de l’article.

Archiver ses positions

Pour disposer d’un historique de nos positions, nous allons ajouter une fonction d’archivage à notre panel de scripts ainsi nommé : archiver.

Dans l’éditeur de scripts, on clique sur Fichier > Nouveau > Fichier script.
Ne reste plus qu’à copier coller les lignes suivantes :

function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [];
menuItems.push({name: 'MAJ Archivage', functionName: 'archiver'});
menuItems.push(null);
spreadsheet.addMenu('Mise à jour des données', menuItems);
}

function updateGlobal_() {
var dataTab = 'archivage';
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(dataTab);
var startRow = 6;
var lastColumn = dataSheet.getLastColumn();

var sourceRow = dataSheet.getRange(2, 1, 1, lastColumn);
dataSheet.insertRows(startRow);

var destRow = dataSheet.getRange(startRow, 1, 1, lastColumn);
sourceRow.copyTo(destRow, {contentsOnly: true});

return true;
}

À la réouverture du fichier, l’onglet « Mise à jour des données » s’affichera :

Ajout onglet menu

Dès que la fonction de mise à jour sera activée, la feuille « Archive » se mettra à jour automatiquement. Le script permet de copier les valeurs les plus récentes, et d’ajouter une ligne au-dessus de la précédente afin de coller les valeurs.

Automatiser son relevé de positions

Ceux qui sont friands d’automatisation connaissent certainement l’option « Déclencheur ». Vous aurez sûrement compris où je veux en venir. En définissant un déclencheur spécifique, vos données se mettront à jour automatiquement. Plus besoin de venir sur le fichier pour relever manuellement vos positions (on pourrait même envisager d’envoyer un mail automatiquement une fois la mise à jour effectuée …).

Toujours dans l’éditeur de scripts, on clique sur la petite pendule « Déclencheurs du projet actuel ».

Là, il suffit d’ajouter les fonctions une à une en tant que déclencheur. Dans mon exemple, je n’appelle pas la fonction qui permet de requêter l’API SemRush.

Déclencheur Google Sheets

Déclencheur Google Sheets

Ingérer ses données dans Google Data Studio

Pour boucler la boucle, vous souhaitez peut-être intégrer vos données dans un de vos dashboard Data Studio. C’est relativement facile puisque l’outil permet de le faire nativement. C’est d’ailleurs tout l’intérêt de travailler via Google Sheets.

Le connecteur Google Sheets étant pointilleux sur l’ordre des lignes et des colonnes, on crée une nouvelle feuille dans notre fichier nommée « Connecteur ».

On ajoute également ce script, à la suite du précédent (ci-après le script complet) :

function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [];
menuItems.push({name: 'MAJ Archivage', functionName: 'archiver'});
menuItems.push(null);
menuItems.push({name: 'MAJ Data Studio', functionName: 'datastudio'});
menuItems.push(null);
spreadsheet.addMenu('Mise à jour des données', menuItems);
}

function archiver() {
var dataTab = 'archivage';
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(dataTab);
var startRow = 6;
var lastColumn = dataSheet.getLastColumn();

var sourceRow = dataSheet.getRange(2, 1, 1, lastColumn);
dataSheet.insertRows(startRow);

var destRow = dataSheet.getRange(startRow, 1, 1, lastColumn);
sourceRow.copyTo(destRow, {contentsOnly: true});

return true;
}

function datastudio() {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ss = sss.getSheetByName('Position Tracker');
var range = ss.getRange('A7:E');
var data = range.getValues();

var tss = SpreadsheetApp.getActiveSpreadsheet();
var ts = tss.getSheetByName('Connecteur');
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}

On crée un nouveau rapport puis on ajoute une nouvelle source de données. Une fois dans le sélecteur de connecteurs, on choisit Google Sheets :

Connecteur Google SheetsOn autorise l’accès aux données.

Accès donnéesOn choisit notre feuille de calcul « old-school-ranking-tool ». On choisit la feuille Connecteur (sans décocher les deux options). On termine ensuite par cliquer sur Ajouter au rapport. On prend soin de vérifier les différents champs ainsi que les types associés.

Définir champs

Pour finir, on ajoute un tableau :

Organisation données

Et le tour est joué 🙂 Nos données seront mises à jour soit manuellement (soit via le script permettant de copier coller les valeurs dans la bonne feuille soit automatiquement via les différents déclencheurs).

Rapport

Comme d’habitude, libre service :

Old School Ranking Report (Data Studio).

Old School Ranking Tool (Google Sheets).

Laisser un commentaire

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

google shopping
Up Next:

Récupérer les données génériques d'un produit sur Google Shopping pour structurer son contenu SEO

Récupérer les données génériques d'un produit sur Google Shopping pour structurer son contenu SEO