Je me suis fait un petit plaisir en développant un petit bout de code javascript permettant de charger de façon asynchrone un lien (ce qui permet de le rendre invisible aux moteurs de recherche), ou une image (ce qui évite qu’elle soit dans le chemin critique de chargement).
Charger des images en asynchrone, c’est notamment utile pour les images pour ce qui concerne les images cachées au chargement ou qui n’ont pas grande valeur ajoutée (rollover de menu, merchandising, etc.) contrairement à d’autres (logo, photos produits, etc.)
Charger des liens en asynchrone évite aux moteurs de crawler trop d’URLs et donc de se concentrer sur les vraies pages à référencer, ce qui évite de trop diluer le page rank.
Pour voir ce que cela donne, n’hésitez pas à regarder le site de Menlook, le spécialiste de la Mode Homme (la boîte pour laquelle je bosse) ;-) vous verrez des éléments qui se chargent en asynchrone, notamment les images du menu (rollover), et certains liens à gauche dans les catégories.
Pour utiliser ma méthode, vous créez vos liens ainsi en PHP :
| PHP | | Copier le code | | ? |
| 1 | |
| 2 | <span dataOBF="<?php echo base64_encode('http://www.monlien.com'); ?>" class="maclass">Mon texte de lien</span> |
| 3 | <span dataOBFimg="<?php echo base64_encode('/path/to/image.jpg'); ?>" alt="Mon Alt" /> |
| 4 |
ou avec Smarty :
| Smarty | | Copier le code | | ? |
| 1 | |
| 2 | <span dataOBF="{$product.link|base64_encode}" class="maclass">{l s='Plus d\'infos'}</span> |
| 3 | <span dataOBFimg="{$urlImage|base64_encode}" alt="Mon Alt" /> |
| 4 |
et cela sera remplacé automatiquement une fois la page chargée (après le reste du contenu synchrone)
Télécharger le fichier avec tout le JavaScript nécessaire (tout le JS ci-dessous s’y trouve, c’est tout ce dont on a besoin)
| Javascript | | Copier le code | | ? |
| 01 | |
| 02 | var dataobf=function() { |
| 03 | // for links |
| 04 | $('span').each(function(index, value){ |
| 05 | if($(this).attr('dataOBF')) { |
| 06 | var url = base64_decode($(this).attr('dataOBF')); |
| 07 | var tClass = null; |
| 08 | var tTitle = null; |
| 09 | var tId = null; |
| 10 | var tStyle = null; |
| 11 | if($(this).attr('class')) { var tClass = ' class="'+$(this).attr('class')+'"'; } |
| 12 | if($(this).attr('title')) { var tTitle = ' title="'+$(this).attr('title')+'"'; } |
| 13 | if($(this).attr('id')) { var tId = ' id="'+$(this).attr('id')+'"'; } |
| 14 | if($(this).attr('style')) { var tStyle = ' style="'+$(this).attr('style')+'"'; } |
| 15 | $(this).replaceWith($('<a href="'+url+'" '+tClass+' '+tTitle+' '+tId+' '+tStyle+'>' + this.innerHTML + '</a>')); |
| 16 | } |
| 17 | }); |
| 18 | // for img (after load) |
| 19 | $('span').each(function(index, value){ |
| 20 | if($(this).attr('dataOBFimg')) { |
| 21 | var url = base64_decode($(this).attr('dataOBF')); |
| 22 | var tClass = null; |
| 23 | var tTitle = null; |
| 24 | var tAlt = null; |
| 25 | var tId = null; |
| 26 | var tStyle = null; |
| 27 | if($(this).attr('class')) { var tClass = ' class="'+$(this).attr('class')+'"'; } |
| 28 | if($(this).attr('alt')) { var tAlt = ' alt="'+$(this).attr('alt')+'"'; } |
| 29 | if($(this).attr('title')) { var tTitle = ' title="'+$(this).attr('title')+'"'; } |
| 30 | if($(this).attr('id')) { var tId = ' id="'+$(this).attr('id')+'"'; } |
| 31 | if($(this).attr('style')) { var tStyle = ' style="'+$(this).attr('style')+'"'; } |
| 32 | $(this).replaceWith($('<img src="'+url+'" '+tClass+' '+tTitle+' '+tAlt+' '+tId+' '+tStyle+' />')); |
| 33 | } |
| 34 | }); |
| 35 | $('a').each(function(index, value){ |
| 36 | if($(this).attr('dataOBF')) { |
| 37 | //alert(base64_decode($(this).attr('dataOBF'))); |
| 38 | $(this).attr('href', base64_decode($(this).attr('dataOBF'))); |
| 39 | } |
| 40 | }); |
| 41 | } |
| 42 | $(document).ready(function() { |
| 43 | dataobf(); |
| 44 | }); |
| 45 |
| Javascript | | Copier le code | | ? |
| 01 | |
| 02 | function base64_decode (data) { |
| 03 | // http://kevin.vanzonneveld.net |
| 04 | // + original by: Tyler Akins (http://rumkin.com) |
| 05 | // + improved by: Thunder.m |
| 06 | // + input by: Aman Gupta |
| 07 | // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
| 08 | // + bugfixed by: Onno Marsman |
| 09 | // + bugfixed by: Pellentesque Malesuada |
| 10 | // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
| 11 | // + input by: Brett Zamir (http://brett-zamir.me) |
| 12 | // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) |
| 13 | // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); |
| 14 | // * returns 1: 'Kevin van Zonneveld' |
| 15 | // mozilla has this native |
| 16 | // - but breaks in 2.0.0.12! |
| 17 | //if (typeof this.window['atob'] == 'function') { |
| 18 | // return atob(data); |
| 19 | //} |
| 20 | var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; |
| 21 | var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, |
| 22 | ac = 0, |
| 23 | dec = "", |
| 24 | tmp_arr = []; |
| 25 | |
| 26 | if (!data) { |
| 27 | return data; |
| 28 | } |
| 29 | |
| 30 | data += ''; |
| 31 | |
| 32 | do { // unpack four hexets into three octets using index points in b64 |
| 33 | h1 = b64.indexOf(data.charAt(i++)); |
| 34 | h2 = b64.indexOf(data.charAt(i++)); |
| 35 | h3 = b64.indexOf(data.charAt(i++)); |
| 36 | h4 = b64.indexOf(data.charAt(i++)); |
| 37 | |
| 38 | bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; |
| 39 | |
| 40 | o1 = bits >> 16 & 0xff; |
| 41 | o2 = bits >> 8 & 0xff; |
| 42 | o3 = bits & 0xff; |
| 43 | |
| 44 | if (h3 == 64) { |
| 45 | tmp_arr[ac++] = String.fromCharCode(o1); |
| 46 | } else if (h4 == 64) { |
| 47 | tmp_arr[ac++] = String.fromCharCode(o1, o2); |
| 48 | } else { |
| 49 | tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); |
| 50 | } |
| 51 | } while (i < data.length); |
| 52 | |
| 53 | dec = tmp_arr.join(''); |
| 54 | |
| 55 | return dec; |
| 56 | } |
| 57 |
D’un point de vue SEO un peu plus poussé, j’ai eu le retour très légitime suivant auquel j’ai répondu :
@m0_oles bots allouent un certain temps au JS. D’après mes tests le base64 suffit mais il suffirait de complexifier l’encryptage utilisé
— Romain BOYER (@RomainBOYER) 20 mars 2013