Vous auriez tort de croire que la réponse est à moitié dans le titre : n’importe quel script ou service externe que vous rajoutez à votre site va vous coûter quelque chose, qu’il soit gratuit ou pas.

Cet article et le suivant sur les pubs sont une transcription d’une conférence donnée à Blend Web Mix 2016. Cliquez ici si vous êtes plus audio que texte.

De quels coûts parle-t-on ?

Ma spécialité étant la performance frontend, j’ai dû m’attaquer au sujet pour des raisons techniques qui m’ont amené à constater que les dégradations en qualité et en performance perçue se traduisaient par un certain nombre de coûts cachés:

  1. des pertes sèches d’activité
  2. un manque à gagner dû au ralentissement du chargement ou au gel de l’interface
  3. une ouverture pour le piratage industriel
  4. une image de marque entamée.

Qui sont les tiers ici ?

  • Analytics, tracking
  • Boutons de partage, réseaux sociaux
  • Tests A/B
  • Widgets divers : cartes, commentaires, chats…

Et étant donnéées leurs spécificités, citons-les à part : les publicités, auxquelles j’ai dédié un article moins technique.

Passons en revue les problèmes et solutions.

1. Les 20 secondes page blanche

Dans le plus spectaculaire des cas, vous pourriez avoir un site qui n’affiche rien pendant plusieurs secondes.

[caption id=”attachment_1199” align=”alignnone” width=”1468”]20 secondes de page blanche, puis affichage du site Veuillez patienter, nous allons prendre votre temps.[/caption]

Pour rajouter un peu de sel sur la plaie, disons que c’est le grand patron qui découvre cela un samedi après-midi de vacances. On va alors se lancer dans une partie de Cluedo pour savoir qui a tué le site et les premiers suspects sont les administrateurs système. Heureusement pour eux, ce sont également fréquemment les seuls à être suffisamment bien équipés en monitoring pour démontrer que les serveurs de la boîte vont bien. Dans le meilleur des cas ils savent mener une analyse rapide du réseau, vue d’un navigateur.

[caption id=”attachment_1200” align=”alignnone” width=”1500”]outil chrome dev tools montrant une requête qui ne répond pas la requête coupable est une longue barre grise, sur-lignée en rouge (forcément)[/caption]

Après analyse, c’est un petit script hébergé sur un serveur qui ne répond pas qui bloque la page. On passe donc en revue les suspect suivants :

  • les développeurs frontend qui n’ont fait que leur devoir en implémentant la solution demandée par le métier,
  • les services marketing et commercial qui ont légitimement besoin de cette solution de [adserving | test A/B | widget | tracker]
  • le service tiers, qui avait donné comme garantie au moment de l’intégration : "On est sur un CDN".

L’enfer c’est les autres

Il est très tentant d’incriminer le tiers à la moindre occasion, et parfois c’est justifié, comme cet incident il y a quelques années où certains tunnels de paiement se mettaient à afficher des erreurs de sécurité.

[caption id=”attachment_1202” align=”alignnone” width=”663”]alerte de sécurité SSL de chrome dûe au serveur jquery une alerte de sécurité du plus bel effet au moment de payer[/caption]

Les pages touchées étaient celles en HTTPS qui incluaient jQuery depuis le CDN code.jquery.com … dont l’administrateur avait oublié cette après midi là de renouveler le certificat de sécurité. Mais il y a plein d’autres raisons pour lesquelles un serveur tiers peut ne pas répondre comme :

  • des attaques mettant à mal votre prestataire ou ses propres prestataires. Dans le cas de l’attaque DDoS contre le DNS Dyn, Twitter n’était plus visible de certains endroits de la planète … tant pis pour les pages incluant les widgets.
  • des erreurs réseau de l‘hyper-espace comme la redirection temporaire du domaine Google vers un site de prévention du terrorisme du gouvernement … Uniquement pour les clients Orange un 17 octobre o_O
  • les wifis gratuits publics (hôtels, aéroports…) qui redirigent certaines requêtes pour insérer dans les pages leurs propres régies publicitaires
  • les firewalls d'états (Chine en tête) ou les proxys d’entreprise qui ont une opinion tranchée sur l’utilisateur Facebook ou Youtube et qui bloquent les domaines : dommage pour les widgets et analytics

Bref : il y a 1001 raisons pour qu’un serveur tiers plante ou ralentisse, il faut donc prévoir son intégration avec cet état de fait.

Savoir intégrer les tiers

Généralement l’intégrateur reçoit simplement comme instruction un mail disant :

Insérez ce script dans le <head>

J’exagère un peu, parfois on a droit à un document Word formaté proprement (mais qui dit la même chose). Il arrive aussi que les développeurs décident d’eux même de faire une bêtise :

  • inclusion de librairies JS / CSS directement depuis leurs CDNs respectifs, comme le préconisent les documentations,
  • récupération des fichiers de polices depuis les serveurs Google Fonts ou autre.

Dans ce dernier cas, il peut y avoir l’excuse de la licence qui n’autorise pas forcément le rapatriement du fichier. Du coup vous faites subir à vos utilisateurs le comportement par défaut de tous les navigateurs (sauf IE) qui n’affichent pas le texte tant que le fichier de police n’est pas présent.

Je vois pas le problème

Pour visualiser les problèmes d’intégration, et surtout leurs conséquences pour l’utilisateur, je ne saurais trop vous recommander les outils suivants :

  • L’indispensable service en ligne WebPagetest : déplier "Advanced Settings", onglet "SPOF" et y mettre les noms d’hôtes à faire planter.
  • L’extension Chrome SPOF-o-Matic qui permet d’alerter, de tester et même de programmer un test comparatif sur WebPagetest.
  • En ligne de commande (pour l’intégration continue par exemple), je vous ai fait un petit script par dessus SPOF-check

[caption id=”attachment_1207” align=”alignnone” width=”663”]capture de l’interface SPOF-o-Matic l’extension SPOF-o-Matic débusquant les potentiels fauteurs de troubles[/caption]

Solutions

Pour ne jamais dépendre d’un tiers, il n’y a qu’environ 2 stratégies :

  1. Les ressources critiques sont à rapatrier sur vos propres serveurs. Le CSS bien sûr, les dépendances JS, les polices si vous en avez le droit.
  2. Tout ce qui reste hébergé ailleurs doit passer en asynchrone : trackers, analytics, widgets, les polices

Il y a certains cas spéciaux comme l’inclusion des tests A/B qui sont à la fois dynamiques et critiques pour le rendu de la page, étant donné qu’ils essayent de le modifier. Mais si vous demandez poliment une mécanique de “timeout” ou un rapatriement périodique du fichier, vous n’aurez plus de soucis.

2. Les retards à l’allumage

Une fois traité le problème impressionnant mais rare de la page blanche dûe à un tiers, reste le problème sournois du ralentissement quotidien, moins visible mais bien plus coûteux. Même avec des inclusions asynchrones on peut se retrouver dans ces situations

[caption id=”attachment_1208” align=”alignnone” width=”916”]un moteur de recherche de voyages mis en attente Moteur de recherche (95% du business) attendant une régie pub (5% du business)[/caption]

Beaucoup (trop) de fonctionnalités dépendent complètement de JavaScript et de moins en moins de développeurs tentent l’amélioration progressive. Dans certains cas comme ici un moteur de recherche complexe, il est même irréaliste de vouloir afficher un moteur sans JS, d’où l’idée de mettre une interface de chargement pour patienter. En sachant que ce code métier critique est inclus en haut de page, quand l’exécuter ? Du pire au mieux :

  1. en haut de page ! Bien sur que NON, le DOM n’est pas forcément disponible à ce moment-là (ce qui ne se voit pas forcément quand on développe sur son poste en local d’ailleurs :) )
  2. on fait confiance à StackOverflow et on attend que document.readyState === 'complete' … Cela correspond à l’événement window.load, c’est-à-dire qu’on va attendre patiemment que toutes les images, iframes et même certains scripts asynchrones soient chargés ! L’utilisateur n’attendra pas, lui.
  3. on attend l’événement document.DOMContentLoaded (en jQuery : $(document).ready(init) ou juste $(init)). Cet événement est retardé par les insertions de scripts même en bas de page, les scripts asynchrones avec l’attribut defer et toute exécution de script, dont le tueur de performances document.write(). La pub utilise toujours cette instruction.
  4. juste après le code HTML du formulaire : vous avez à la fois la garantie que le DOM est présent, et d’être exécuté avant tous les événements navigateur. C’est ce que je recommande pour du code critique comme ce formulaire.

Il y a donc un conflit ouvert entre le tiers inclus et votre code métier, que vous pouvez résoudre en exécutant plus tôt votre code. Si vous persistez à vouloir dépendre de l’événement DOMContentLoaded pour exécuter votre code, il va falloir travailler au corps l’inclusion des scripts des tiers :

  • s’ils ne sont pas lourds à l’exécution et importants, le plus bas possible dans la source avec l’attribut standard async (IE10 +)
  • s’ils sont secondaires, en inclusion asynchrone classique après le chargement de la page (natif façon Analytics ou $.getScript)
  • refuser les scripts dépendant ou utilisant document.write() (d’ailleurs partiellement dépréciée par Chrome).

La pub est spéciale : les régies ne peuvent pas se passer de l’instruction document.write() car leurs propres fournisseurs l’utilisent peut-être. La solution technique est simplement d’inclure la publicité en iframe, ce qui interdit certains formats invasifs. Désolé de vous le dire mais si votre business dépend de la pub et que vous vous êtes engagé à afficher des pubs qui peuvent déborder de leur cadre, il n’y a pas de solution purement technique ! On va voir dans un autre article qu’il y a matière à bien faire, mais que les décisions sont loins d’être techniques.

Après le chargement

Vous avez forcément déjà constaté les effets d’interface gelée voire de crash sur mobile, ou vous avez eu l’impression que votre ordinateur portable allait décoller de votre bureau par la seule force de ses ventilateurs. Pour faire le test, je vous conseille de visiter cette page parodique sans adblock, voire sur mobile : http://worldsmostshareablewebsite.greig.cc/, qui se contente d’inclure plusieurs fournisseurs de boutons de partage. Sur une tablette Nexus 7, l’interface est gelée pendant 20 secondes. La nouvelle bataille de la performance frontend, est clairement les temps d’exécution abusifs côté client. J’ai déjà eu le cas avec de “simples” inclusions de bouton de partage (Facebook et G+ en tête) mais c’est le cas avec n’importe quel script qui va modifier l’interface. Il y a un principe général à comprendre avec les tiers :

Si c’est rapide à intégrer, c’est que ça va ramer

Les tiers, en particulier s’ils ont une version gratuite, ont 2 besoins antinomiques : simple et passe-partout. Le tutoriel doit paraître simple et consiste généralement en une inclusion de script et à la création d’un peu de HTML. À l’image du bouton Facebook.

[caption id=”attachment_1212” align=”alignnone” width=”540”]code d’inclusion du bouton facebook Trop simple pour être performant[/caption]

Remarquez que l’insertion du script est généralement asynchrone comme ici, car les tiers ont fait des efforts pour ne pas bloquer les chargements ces dernières années.

Détecter le problème

Maintenant mettez vous à la place du développeur de ce code : comment faire pour savoir où afficher son widget ? La réponse est aussi simple que contre-performante : en s’auto-exécutant dès que possible, et en scannant le DOM régulièrement. Selon la lourdeur initiale de votre site, on peut vite arriver à de jolis blocages dont vous ne comprendrez l’origine qu’avec un profilage en règle. Notez qu’il faut utiliser de vraies machines pour tester correctement tout cela.

[caption id=”attachment_1214” align=”alignnone” width=”1119”]capture d’écran de l’outil de profilage chrome 3 longues secondes d’exécution pour ce seul tiers[/caption]

Le fichier mis en cause ici (post-widget.js surligné en gris) provient effectivement d’un tiers qui inclut des boutons sociaux. Il bloquait l’interface et faisait même régulièrement planter un iPad mini 2. À sa décharge, la page visée était lourde et contenait 150 éléments que le script recherchait et modifiait. Il n’existait pas d’outil dédié — même payant — permettant de déceler facilement qui était responsable des pics de charge processeur sur une page. J’ai du écrire un petit script du nom de 3rd-party-cpu-abuser qui exploite la timeline de Chrome Dev Tools pour mettre des noms sur les responsables :

[caption id=”attachment_1215” align=”alignnone” width=”417”]tableau de statistiques de consommation CPU 80% du CPU consommé l’est par les tiers[/caption]

WebPagetest a également récemment introduit une visualisation du CPU répartie par fichier JS : onglet “chrome”, case “capture devtools timeline”).

Pour débloquer la situation, je me suis contenté comme souvent d’aller lire la documentation pour y chercher 2 optimisations classiques :

  • comment ne pas initialiser le script automatiquement, afin d’éviter l’effet Big Bang du début de construction de page et ne l’exécuter qu’au moment opportun.
  • comment indiquer le DOM à modifier, pour éviter les recherches DOM coûteuses

Pratiquement tous les fournisseurs de widget proposent maintenant ces options dans leurs APIs. Si ce n’est pas le cas, c’est mauvais signe donc partez chez le concurrent !

3. L’espionnage industriel

Les réseaux sociaux

La performance

Rajouter quelques boutons de partage n’est pas aussi gratuit que ça en a l’air. Il y a bien sûr la performance utilisateur, qui en pâtit.

[caption id=”attachment_1218” align=”alignnone” width=”1500”]comparaison de screenshot montrant le chargement d’une page wordpress avec et sans boutons 4 boutons = ralentissement de l’affichage et du temps de chargement[/caption]

Sur cette page wordpress simple et optimisée, rajouter 4 boutons natifs multiplie le temps de 1er affichage et de chargement par deux !

Les taux de transformation

Mais il faut aussi se demander si ces boutons apportent vraiment quelque chose au site. Par exemple Smashing Mag en 2012 avait constaté qu’en ENLEVANT le bouton Facebook, leurs utilisateurs partageaient plus les articles sur Facebook !

[caption id=”attachment_1219” align=”alignnone” width=”839”]le traffic depuis Facebook a augmenté depuis que nous avons enlevé les boutons FaceBook de nos articles Smashing Mag : “le trafic depuis Facebook a augmenté depuis que nous avons enlevé les boutons FaceBook de nos articles” (2012)[/caption]

NB: Entretemps Facebook a sorti un bouton “Partage” plutôt que simplement “Like”, et Smashing Mag l’a ré-intégré de manière statique.

Autre exemple : un test A/B fait par un site de e-commerce qui a consisté à SUPPRIMER ces boutons de la page produit et leur a permis de constater que cette suppression AUGMENTAIT les taux de conversion de 12%. Ils supposent que finalement ces boutons n’étaient qu’une distraction à ce moment-là, et que les chiffres de partage affichés, proches de 0 comme souvent dans le e-commerce, renvoyaient un sentiment négatif. J’y ajouterais que la légère dégradation de performance induite par ces boutons a dû contribuer :)

Bref : comme pour n’importe quelle fonctionnalité, demandez vous si elle ne dessert pas plutôt votre produit, ou s’il n’y a pas une meilleure manière de l’intégrer.

Nourrir vos concurrents

La raison d’être secondaire de ces boutons pour Google et Facebook est qu’il leur permet de mieux qualifier leurs propres utilisateurs, en dehors de leurs propres murs. Même lorsque l’utilisateur n’interagit pas avec, leur simple présence signale à G. et FB qu’un de leurs utilisateurs visite une page, leur permettant ainsi d’affiner les profils. Dans le cas de Google, l’utilisateur n’a même pas besoin d’avoir un compte. Ne me lancez pas sur le respect de la vie privée, d’autres le font mieux que moi, parlons plutôt argent. À toute fin utile, il faut tout de même rappeler que Google mange 42% du marché de la publicité en France (95% des 47% du CA de la search).

[caption id=”attachment_1220” align=”alignnone” width=”466”]répartition du marché de la publicité en 2014 : 47% pour le search et 31% pour le display Marché de la pub en 2014[/caption]

Pour le marché qui vous intéresse probablement, c’est-à-dire le “display” (affichage de bannières classiques) on estime que Facebook en capte 30%. Ce que les annonceurs apprécient, outre l’audience, c’est que leur base est hyper qualifiée, et c’est en partie grâce aux sites qui incluent les boutons. Déjà que ces boîtes s’évitent un maximum d’impôts en France, ce n’est pas la peine de leur faire de cadeau supplémentaire en utilisant leurs scripts tels quels.

Les solutions

En admettant que vous ayez déterminé que les boutons de partage étaient vraiment bons pour votre site (typiquement, un site d’articles), il existe des manières d’inclure qui ne nourrissent pas vos concurrents, sont performantes et respectent votre charte graphique :

  1. les boutons statiques, qui sont des liens simples formatés permettant le partage et que vous pouvez mettre par dessus de simples icônes
  2. si vous avez besoin de fonctionnalités supplémentaires comme des icônes toutes faites, afficher les compteurs ou avoir des analytics, vous pouvez rajouter un peu de JavaScript. Voici une solution open-source parmi d’autres
  3. enfin il existe quantité de services tiers (addThis, shareThis, shareAholic …) mais on retombe sur les travers habituels des tiers : il faut benchmarker les temps de chargement car ils vont du simple au triple et le business model de certains comme shareAholic est de revendre les données utilisateur

Les tiers des tiers de vos tiers

Le problème

Quand il n’y en a qu’un ça va

S’il est normal de faire confiance à un prestataire direct, la confiance ne peut que s’étioler au fur et à mesure de la chaîne d’appel de leurs partenaires. Or quand vous accordez techniquement les pleins pouvoirs à votre prestataire (une simple insertion de script), vous les accordez également à toute une chaîne de sociétés dont vous n’aviez peut-être jamais entendu parler. Je vais utiliser l’outil RequestMap pour visualiser un affichage sur la Une du journal Le Monde.

[caption id=”attachment_1223” align=”alignnone” width=”778”]visualisation des requêtes faites vers les 1er tiers Appels vers les tiers de 1er niveau[/caption]

Chaque cercle est un nom de domaine, les flèches sont les appels. Au centre en bleu clair, le domaine principal www.lemonde.fr qui appelle 2 sous-domaines de statiques (s1 et s2.lemde.fr). Tous les autres domaines (cercles) appartiennent aux tiers de 1er niveau et correspondent à une quinzaine de sociétés. On y trouve 3 solutions d’analytics, une solution de test A/B (Kameleoon), un tracking de réseau social (Po.st), FaceBook, un moteur de recommandation d’articles (Outbrain ici), Cedexis … Ce sont les tiers de 1er niveau : ceux que l’on inclut de manière tout à fait consciente. Les relations avec ces tiers sont régies par un contrat direct ou par l’acceptation des CGU, et tant que les principes d’intégration cités plus haut dans cet article sont respectés, je n’ai plus rien à rajouter.

Puis arrive le moment où l’on contacte la régie pub (SmartAd en l’occurrence, à droite sur le graphe précédent, à gauche sur le graphe suivant).

[caption id=”attachment_1225” align=”alignnone” width=”1006”]Tiers de niveau 2, 3 et 4 … Oh la belle roseAppel des tiers de niveau 2, 3 et 4 … Oh la belle rose[/caption] Une fois sur son domaine, la régie appelle une dizaine de sociétés, principalement des tags de tracking, puis 2 systèmes de mise aux enchères de mon profil utilisateur. C’est la société de RTB CasaleMedia qui prend le relai, et qui contacte une vingtaine d’autres sociétés. Cela c’est côté client, on ne sait pas combien d’enchérisseur ont accès au profil utilisateur côté serveur. L’enchère a été gagnée par une société de retargeting (Turn) qui elle-même contacte une vingtaine de sociétés. En tout c’est 50 sociétés qui ont été contactées côté client. Si le script du 1er tiers inclus de manière classique, ces 50 sociétés avec qui vous n’avez aucun contrat ont tout pouvoir sur la page. Il leur est techniquement possible de la modifier (on a vu des sociétés malhonnêtes remplacer les publicités des autres) ou d’y récupérer des informations : outre les informations de navigation, elles pourraient cibler un site de e-commerce et estimer ses ventes et leur nature par exemple, simplement en scannant le DOM. Ces scénarii sont pratiquement indétectables et quand on voit qu’il arrive que des pirates diffusent des virus grâce aux régies publicitaires, il n’est pas irréaliste d’imaginer une société voulant récupérer des informations chez son concurrent.

Les solutions

Se parler !

Les premières actions ne sont pas techniques du tout. D’abord, lister quelles sociétés atterrissent sur vos pages, avec des solutions :

Ensuite, du côté des contrats signés avec vos partenaires, vérifiez que leurs partenaires à eux vous conviennent et demandez-vous quels engagements de moyens ils ont et pourquoi pas imaginer un système de pénalités. Les régies savent se montrer réactives lorsqu’un de leurs clients leur signale un problème avec un prestataire, mais détecter le problème en question est très compliqué. Enfin, il faut établir un dialogue entre les équipes IT et les utilisateurs des services tiers (marketing, produit, commerciaux …), en faisant un point régulier “Tiers”, avec l’ordre du jour suivant :

  1. l’IT fait l’inventaire des tiers de 1er niveau et remontent éventuellement les problèmes rencontrés
  2. côté business, on classe par ordre d’importance les tiers … oui il va y avoir du débat !
  3. décisions de suppression
  4. décisions quant à l’ordre de chargement

On se retrouve à prendre des décisions complexes car comment décider de ce qui est plus important entre un test A/B, les analytics, le player vidéo, les pubs, la carte ou les boutons de partage ? Il faut pourtant que ce soit une décision réfléchie car jusqu’ici, cette décision était de fait laissée à l’intégrateur et au navigateur …

Côté technique

Si votre business model vous permet de vous passer des publicités invasives, ce qui est le cas des sites de e-commerce par exemple, alors je ne saurais trop vous recommander la bonne vieille technique de l’inclusion en iframe. Cela gomme les inconvénients de document.write(). L’attribut sandbox vous permet (depuis IE9) d’accorder aux tiers d’accéder à votre page, vos cookies ou le droit d’ouvrir une popup. <iframe sandbox="allow-scripts" src="carre_pub.html" /> suffit pour les publicités classiques : il autorise JavaScript, mais la sous-page ne peut rien faire sur la page principale. Si vous avez besoin de communiquer, l’API postMessage est là pour ça !

Pour aller plus loin, mais je ne l’ai encore jamais vu en production, il y a le standard Content Security Policy (à partir de Edge) qui permet entre autres de limiter les pouvoirs donnés aux tiers inclus directement en JavaScript. Pour une transition en douceur, vous pouvez passer par une phase d’observation des erreurs côté client (report-uri). Maintenant on ne va pas se mentir : la vraie difficulté, c’est de faire admettre que l’on veut limiter le pouvoir des tiers, pas de les en empêcher !

Conclusion

Les tiers posent leurs lots de problèmes mais ils ont pratiquement tous une solution technique, au contraire des publicités. Du moment que l’on fait attention au moment de l’intégration et que l’on surveille les régressions de performance, on évite la plupart des écueils. Si vous avez plus de quelques services externes et qu’ils peuvent mettre en péril votre business, mettre en place une solution de monitoring dédiée est à envisager rapidement.