Création et adaptation des moteurs de recherche personnalisés Google (CSE - Custom Search Engine)

Introduction

L'indexation des pages d'un site dans l'index global de Google peut prendre du temps, il est en effet impossible de gouverner l'arrivée de GoogleBot sur les nouveaux articles déclarés dans un sitemap par exemple.

Aussi Google propose les moteurs de recherche personnalisés ou les moteurs CSE (Custom Search Engine), moteurs qu'il est possible d'encapsuler dans son propre site Web et pour lesquels l'indexation des pages peut être réalisée à la demande.

google index

Un moteur Google CSE intégré dans son site Web permet aux internautes d'obtenir dans les résultats de la recherche les tout derniers articles parus alors que ceux-ci ne sont pas encore répertoriés dans l'index global de Google.

Voici un exemple d'incorporation d'un moteur de recherche CSE Google dans SQLPAC (http://www.sqlpac.com/recherche), exemple avec une recherche sur les mots clés "Javascript" et "createElement".

Dans les résultats de la recherche, les mots clés "Javascript" et "createElement" doivent afficher en tête de liste l'article conception-html-dynamique-suppression-document.write.htm paru le 30/12/2010, article qui est le plus pertinent. La recherche avec le moteur CSE intégré dans SQLPAC affiche bien cet article en tête de liste à l'internaute dans les résultats, contrairement à la recherche dans l'index global de Google. Le fichier sitemap contient bien l'article en question mais Googlebot n'est pas encore passé dessus et l'indexation de cet article n'est pas prédictible :

google index global

Il n'y a pas d'exclusions lors de l'interrogation, les moteurs personnalisés sollicitent les 2 versions de moteurs lors de l'affichage des résultats :

  • le moteur global Google.
  • le moteur local CSE.

Cet article présente la mise en place, l'optimisation et l'adaptation de l'index Google CSE dans SQLPAC. Des adaptations sont nécessaires pour assurer un suivi efficace des mots clés saisis par les internautes dans le moteur personnalisé, mais aussi si des options complémentaires de recherche sont souhaitées.

Création rapide du moteur CSE

La création d'un moteur personnalisé CSE Google est très simple avec les interfaces graphiques offertes par Google : se rendre à l'URL ci-contre http://www.google.com/cse/ (un compte Google est nécessaire).

Panneau de configuration
1. Généralités Les informations générales sur le moteur à créer sont d'abord renseignées : nom du moteur de recherche, description etc... Un identifiant unique est alors attribué au nouveau moteur CSE. ID unique du moteur de recherche : 013836751360076949567:qmnlyz2qlfo Cet identifiant est très important car il sera utilisé ultérieurement en Javascript. panneau configuration general
2. Sites L'interface propose les sites à inclure dans le moteur personnalisé. Dans le cas de SQLPAC, seul le site http://www.sqlpac.com/* est inclus, ce moteur ayant pour vocation de rechercher uniquement dans SQLPAC. panneau configuration sites
3. Éléments graphiques Les éléments graphiques comme l'option d'hébergement, la disposition, les styles... sont ensuite définis. Pour SQLPAC, l'option Search Element est choisie avec une présentation en largeur maximale et les styles sont personnalisés en adéquation avec le style du site SQLPAC. panneau configuration styles

Le menu "Panneau de configurationObtenir le code" affiche le code Javascript pour intégrer le moteur de recherche CSE dans une page du site, voici un extrait :

<div id="cse" style="width: 100%;">Loading</div>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
  google.load('search', '1', {language : 'fr'});
  google.setOnLoadCallback(function() {
    var customSearchControl = new google.search.CustomSearchControl('013836751360076949567:qmnlyz2qlfo');
    
    customSearchControl.draw('cse');
  }, true);
</script>

<link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" />
<style type="text/css">
  .gsc-control-cse {
    font-family: Verdana, sans-serif;
    border-color: #FFFFFF;
    background-color: #FFFFFF;
  }
...
</style>

Ce simple bout de code est opérationnel immédiatement lorsqu'il est incorporé dans le code HTML.

Cinématique Javascript du moteur de recherche CSE

Que se passe-t-il lors d'une recherche ? Le premier bloc <div id="cse"></div> est capital.

<div id="cse" style="width: 100%;">Loading</div>

L'identifiant id="cse" de cet élément div permettra à Google de savoir où incorporer dynamiquement le bloc iframe des résultats de la recherche, car les résultats sont en effet affichés dans un bloc iframe.

<div id="cse" style="width: 100%;">Loading</div>
...
  <iframe>
    <html>...</html>
 </iframe>
...

Les APIs Javascript de Google sont incluses avec http://www.google.com/jsapi. Lors de cette inclusion, un objet google est instancié. :

<script src="http://www.google.com/jsapi" type="text/javascript"></script>

La fonction google.load('search', '1', {language : 'fr'}) charge la version 1 du module search (CSE) avec la langue fr en option : google.load ('<module>','<version>', {options}).

google.load('search','1',{language : 'fr'});

La méthode onLoadCallBack appliquée sur l'objet google définit la fonction ou le code Javascript à exécuter après chargement du module search.

Un nouvel objet Javascript CSE appelé customSearchControl est alors créé avec en paramètre l'identifiant unique du moteur de recherche CSE :

 var customSearchControl = new google.search.CustomSearchControl('013836751360076949567:qmnlyz2qlfo');

L'identifiant du bloc div (id=cse) dans lequel afficher le bloc iframe des résultats est indiqué avec la méthode draw de l'objet customSearchControl. Et comme la méthode l'indique (draw), le bloc de recherche Google CSE (bouton de recherche, champ de saisie des mots clés...) est aussitôt dessiné et incorporé dans le bloc <div id=cse> lors de l'appel de cette méthode :

customSearchControl.draw('cse');

L'indexation à la demande du moteur CSE Google à l'aide des sitemaps

Si un compte Google Webmaster Tools existe pour le compte Google, le panneau de configuration du moteur Google CSE propose automatiquement les sitemaps paramétrés avec l'outil Google Webmaster Tools dans l'écran d'indexation à la demande à l'aide de sitemaps.

Panneau de configuration - Indexation Un sitemap peut être utilisé pour l'indexation à la demande, par exemple un sitemap contenant les derniers articles parus et à indexer immédiatement dans le moteur Google personnalisé CSE. Avec les sitemaps, le moteur CSE fonctionne par lot de 10 pages. Le moteur CSE parcourt et indexe en priorité les 10 premières pages ayant les plus hautes priorités et les dates de modifications les plus récentes. Il faut attendre 24 heures pour pouvoir indexer à la demande 10 pages supplémentaires. La limite de 10 pages par tranche de 24 heures est faible certes, mais le moteur Google CSE est gratuit et présente l'avantage de ne pas avoir à attendre l'indexation dans l'index global de Google. panneau configuration indexation avec sitemaps
<?xml version="1.0" encoding="UTF-8"?> 
<urlset ...>
 <url> 
  <loc>http://www.sqlpac.com/referentiel/docs/unix-vi-guide.html</loc> 
  <lastmod>2010-12-06</lastmod> 
  <changefreq>monthly</changefreq> 
  <priority>0.5</priority> 
 </url> 
</urlset> 

Adaptations (styles, javascript)

Adaptations et normalisations des styles

Des styles personnalisés ayant été définis, le code généré par Google présente des balises de style <link> et <style> :

<link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" />
<style type="text/css">
  .gsc-control-cse {
    font-family: Verdana, sans-serif;
    border-color: #FFFFFF;
    background-color: #FFFFFF;
  }
 ...
</style>

Les balises <link> et <style> écrites après la balise <body> ne passent pas les validations du W3C :

Erreur document type does not allow element "LINK" here
Erreur document type does not allow element "STYLE" here

Ces balises, interdites dans le corps de la page, doivent être incluses dynamiquement dans l'entête (<head>....</head>) : les méthodes createElement, setAttribute et appendChild du langage Javascript vont permettre de réaliser cette opération technique. Pour plus d'informations sur ces méthodes Javascript : Ajout et suppression d'éléments avec Javascript - Suppression de document.write

Dans un premier temps, tous les éléments de style inclus entre <style type="text/css"> et </style> sont écrits dans un fichier cse.css (/css/themes/grey/cse.css), fichier qui est ensuite incorporé dynamiquement dans l'entête grâce au bout de code Javascript ci-dessous :

<script type="text/javascript">
<!--
    var v_head = document.getElementsByTagName("head")[0]; 
    v_link_csse = document.createElement("link");
    v_link_csse.setAttribute("href","/css/themes/grey/cse.css");
    v_link_csse.setAttribute("type","text/css");
    v_link_csse.setAttribute("rel","stylesheet");
    v_link_csse.setAttribute("media","screen");
    v_head.appendChild(v_link_csse);
-->
</script>

La délocalisation de ces éléments de style unitaires dans un fichier de style cse.css permet une maintenance plus aisée des styles du moteur de recherche.

La feuille de style http://www.google.com/cse/style/look/default.css est intégrée de la même manière avec Javascript :

<script type="text/javascript">
<!--
    var v_head = document.getElementsByTagName("head")[0]; 
    v_link_csse_default = document.createElement("link");
    v_link_csse_default.setAttribute("href","http://www.google.com/cse/style/look/default.css");
    v_link_csse_default.setAttribute("type","text/css");
    v_link_csse_default.setAttribute("rel","stylesheet");
    v_link_csse_default.setAttribute("media","screen");
    v_head.appendChild(v_link_csse_default);
-->
</script>

Adaptations du Javascript (lisibilité)

Pour la lisibilité du code et la maintenance future, les actions à réaliser après chargement du module search sont délocalisées dans une fonction appelée gseDraw au lieu d'incorporer le code Javascript en paramètre de la fonction setOnLoadCallBack :

<div id="cse" style="width: 100%;">Chargement...</div>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
  google.load('search', '1', {language : 'fr'});
  
  gseDraw = function () {
    
    var customSearchControl = new google.search.CustomSearchControl('013836751360076949567:qmnlyz2qlfo');
    customSearchControl.draw('cse');

  }
  google.setOnLoadCallback(gseDraw,true);
</script>

Déclencher automatiquement une recherche par programmation

Le moteur de recherche CSE est d'ores et déjà opérationnel. Une recherche peut être pré définie et effectuée au tout premier chargement du bloc iframe par programmation grâce à la méthode execute de l'objet customSearchControl : customSearchControl.execute('<query>') :

<script type="text/javascript">
 ...
customSearchControl.draw('cse');
customSearchControl.execute('oracle');
 ...
</script>

Une recherche avec le mot clé oracle sera automatiquement déclenchée au premier chargement de la page.

Dans le site SQLPAC, la page de recherches incorporant le moteur Google CSE est appelée avec l'adresse URL http://www.sqlpac.com/recherche?q=<motsclés> (exemple : http://www.sqlpac.com/recherche?q=oracle+transparent+gateway). L'alias "recherche" dans l'adresse URL correspond au script prp_srch.php5 : une règle de réécriture Apache a été définie pour ce script dans le fichier .htaccess.

.htaccess
RewriteRule ^recherche$      prp_srch.php5 [L]

Il est alors simple en combinant Javascript et PHP de déclencher automatiquement la recherche avec les mots clés contenus dans la variable HTTP q lors de l'ouverture de la page de recherche :

<script type="text/javascript">
 ...
customSearchControl.draw('cse');
   <?php
     if (isset($_GET["q"])) {
       $q = $_GET["q"];
       if ($q != " ") {
         echo "  customSearchControl.execute('".$q."');";
       }
     }
    ?>
 ...
</script>

Contournement de la problématique du bloc iframe avec Google Analytics et des options complémentaires de recherche

Ce bloc iframe est particulièrement problématique : si l'internaute est arrivé sur cette page et saisit de nouveaux mots clés pour affiner sa recherche, seul le bloc iframe est rafraîchi avec les nouveaux résultats, l'adresse URL de la page n'est pas rafraichie.

L'adresse URL n'étant pas rafraichie, l'outil de mesure d'audience Google Analytics n'est pas déclenché et ne peut pas prendre en compte dans ses statistiques l'adresse URL avec les nouveaux mots clés saisis. Ce point est très problématique pour mieux appréhender ce que peuvent rechercher les internautes dans le moteur CSE intégré.

Autre point noir : il y a parfois besoin d'affiner les critères de recherche (ajout de catégories, périmètre dans lequel chercher les documents, dates etc...). Ce qui n'est pas possible en l'état actuel.

Pour contourner ces 2 points noirs :

  • Cacher la barre d'outils par défaut du moteur de recherches CSE (champ de saisie, bouton Rechercher).
  • Créer un formulaire personnalisé.

Voici un exemple de formulaire personnalisé : un champ pour les mots clés, une liste de catégories et un périmètre de recherche (Articles uniquement, tout).

formulaire google search personnalise

Masquer la barre d'outils de recherche du moteur CSE

La barre d'outils par défaut du moteur de recherches Google CSE peut être très simplement masquée en appliquant en CSS la propriété display à none à tous les éléments contenus dans div id=cse ayant pour classe gse-search-box

/** cse.css  */
#cse gse-search-box {
 display:none;
}

Si l'identifiant du bloc div est différent, bien entendu la syntaxe sera #<id div> gse-search-box { ... }.

Création du formulaire personnalisé

Une fois la barre d'outils par défaut du moteur CSE masquée, un formulaire est créé avec un champ de saisie des mots clés et des options complémentaires éventuelles : dans cet exemple une liste de catégories et le périmètre de recherches (Articles uniquement ou tout le site).

<form class="formsearch" action="/recherche" name="frm_search_full" accept-charset="UTF-8">   
<p>
  <input class="inputbox" type="text" name="q" size="70" value="dbcc">

  <select name="categorie"> 
    <option value="all"  selected >Toutes les catégories</option> 
    <option value="sybase" >Sybase</option> 
    <option value="oracle" >Oracle</option> 
    <option value="ms sql" >MS SQL</option> 
    <option value="mysql" >MySQL</option> 
    <option value="postgresql" >PostgreSQL</option> 
  </select> 

  <input class="bsubmit" type="submit" title="Rechercher" name="sa" value="" 
     onclick="javascript:document.frm_search_full.submit();" >
</p>

<p>
  <input type="radio" name="perimetre"  value="htm" >Articles uniquement
  <input type="radio" name="perimetre" checked value="all" >Tout le site (news, thèmes, articles ...)
</p>

</form>

Le formulaire ainsi défini force le rechargement de la page /recherche avec les nouveaux paramètres, ce que Google Analytics pourra détecter pour une analyse fine des recherches réalisées par les internautes sur le moteur personnalisé.

  • /recherche?q=dbcc&categorie=sybase&perimetre=all
  • /recherche?q=transparent+gateway&categorie=oracle&perimetre=htm

Lorsqu'une catégorie est sélectionnée (catégorie différente de "all"), la valeur de la catégorie est ajoutée aux mots clés saisis dans la requête : requête = catégorie <mots clés>.

Lorsque le périmètre est restreint aux articles uniquement, la recherche est limitée aux fichiers ayant pour extensions *.htm ou *.pdf pour les mots clés saisis : requête = <mots clés> filetype:htm OR filetype:pdf.

Par programmation en combinant Javascript et PHP :

<script type="text/javascript">
 ...
 customSearchControl.draw('cse');

  <?php
       if ($categorie !="all") { $q = $categorie." ".$q ;}
       if ($perimetre =="htm") { $q = $q." filetype:".$perimetre." OR filetype:pdf" ;} 
       if ($q != " ") {
          echo "  customSearchControl.execute('".$q."');";
       }
  ?>
 ...
</script>