Sur la page mobile médiane du Web Almanac 2024, 168 kilooctets de JavaScript provenaient du site lui-même et 375 kilooctets de tiers.1 Plus de la moitié du script d’une page ordinaire, en poids, avait été écrite par quelqu’un d’autre que le propriétaire du site. Le chapitre de l’Almanac consacré aux tiers en a trouvé sur 92 % des pages, le script étant le type de requête tierce le plus courant.2 Le script d’un réseau publicitaire, celui qu’un éditeur ajoute pour diffuser ses publicités, fait partie de ces requêtes. Ce que ce script coûte à la page au chargement dépend moins de ce qu’il fait que de la façon dont est écrit l’élément qui le charge.

Le navigateur s’arrête devant un élément script qui ne porte aucun attribut

Selon la norme HTML Living Standard, un navigateur dispose de trois façons de traiter un script externe, qui ne diffèrent que par un attribut de l’élément.3 La première, sans aucun des deux attributs, est le comportement par défaut : le script « est récupéré et évalué immédiatement, en bloquant l’analyse jusqu’à ce que ces deux opérations soient terminées ». La deuxième, defer, récupère le fichier en parallèle de l’analyse et l’évalue « lorsque l’analyse de la page est terminée ». Avec la troisième, async, le fichier est également récupéré en parallèle, mais évalué « dès qu’il est disponible (éventuellement avant la fin de l’analyse) ». Seul le premier mode retient l’analyseur pendant que le fichier traverse le réseau, et rien de ce qui suit l’élément n’est affiché avant l’arrivée du fichier.

L’audit Lighthouse de Google transforme cette distinction en un test qu’un éditeur peut lancer sur sa propre page. Il signale tout élément script situé dans l’en-tête du document qui ne porte ni defer ni async.4 Le rapport « dresse la liste de toutes les URL qui bloquent le premier affichage de votre page ». La taille ne fait pas partie de cette définition, pas plus que la finalité. Un script d’analyse d’audience, un script publicitaire et un chargeur de polices sont traités de la même façon s’ils se trouvent dans l’en-tête sans attribut.

Les scripts tiers sont le cas pour lequel les recommandations de chargement ont été écrites

Les recommandations de web.dev sont directes au sujet des scripts provenant d’un autre site. Les scripts synchrones, indiquent-elles, « retardent la construction du DOM et l’affichage », le DOM étant le modèle de travail du document dans le navigateur.5 La règle qui en découle est de « toujours charger les scripts tiers de manière asynchrone, sauf si le script doit s’exécuter avant que la page puisse être affichée ». async convient à un script qui doit s’exécuter tôt dans le processus de chargement ; defer convient aux « ressources moins critiques », l’exemple donné étant un lecteur vidéo situé sous la ligne de flottaison. Un script publicitaire qui travaille une fois le texte à l’écran relève, selon ce critère, des ressources moins critiques.

La pratique s’est répandue, mais pas sur toutes les pages. Le Web Almanac 2024 a trouvé async sur 87 % des pages, contre 76 % en 2022, et defer sur 47 %, contre 42 %.1 Ces chiffres décrivent les pages dans leur ensemble. Une page dont les propres scripts sont différés peut encore contenir un élément bloquant fourni par un tiers. Un extrait de code d’installation, à moins que l’éditeur ne le modifie, se charge comme le réseau l’a écrit.

Un script qui attend le DOM n’a pas de premier affichage à bloquer

Le navigateur signale par un événement le moment où l’analyseur a fini de construire le DOM. Selon MDN, DOMContentLoaded « se déclenche lorsque le document HTML a été entièrement analysé et que tous les scripts différés » ont été téléchargés et exécutés.6 L’événement n’attend ni les images, ni les sous-cadres, ni les scripts async. Un script qui commence son travail à ce moment démarre donc une fois le texte présent, sans attendre la dernière image.

Le script d’intégration AdBubbles, adbubbles.js, se charge une fois le DOM de la page prêt. C’est un unique fichier statique, servi via le cache de Cloudflare et écrit en JavaScript simple sans aucune dépendance. Les données propres au site qu’il lit forment elles aussi un fichier statique, régénéré lorsqu’une campagne change et mis en cache en périphérie du réseau. Une page vue ne coûte donc rien au serveur publicitaire, et la seule requête dynamique est une petite balise de mesure. Le script d’intégration n’analyse que le périmètre configuré par l’éditeur, et ignore les titres, les liens, le code, le texte préformaté, les contrôles de formulaire, la navigation, l’en-tête, le pied de page et tout ce qui est marqué data-noads. Les notes d’installation décrivent le réglage du périmètre.

Ouvrir un compte éditeur ne coûte rien, pas plus qu’ajouter le script d’intégration à un site. Un éditeur qui ajoute un site peut demander une exploration montrant lesquels de ses mots peuvent actuellement être vendus. Le périmètre, le nombre maximal de bulles par page et les catégories d’annonceurs exclues se choisissent depuis le même compte.

La balise envoyée quand un lecteur s’en va est l’autre moitié du coût

Le moment où un lecteur s’en va est l’autre occasion pour un script de le ralentir. Le code d’analyse d’audience qui envoyait ses données au déchargement s’appuyait autrefois sur des techniques telles qu’« un appel XMLHttpRequest synchrone bloquant ».7 MDN note que toutes ces méthodes « bloquent le déchargement du document, ce qui ralentit la navigation vers la page suivante ». La méthode sendBeacon les remplace. Elle envoie une petite requête HTTP POST de manière asynchrone. Le navigateur transmet les données « lorsque l’agent utilisateur en a l’occasion, sans retarder le déchargement ni la navigation suivante ».

Le script d’intégration envoie ses données avec sendBeacon, et il envoie trois types de balises de mesure. Un affichage est envoyé par chargement de page. Une ouverture est envoyée lorsqu’une bulle est restée visible une seconde, et un clic lorsqu’un lecteur suit le lien d’une bulle. Rien d’autre ne quitte la page.

AdBubbles ne dépose aucun cookie, ne stocke aucun identifiant et ne collecte aucune donnée personnelle sur les lecteurs. Le pays du lecteur est lu à partir d’un en-tête de requête Cloudflare plutôt qu’à partir d’une adresse IP conservée. Associer les mots des pages d’un éditeur à l’annonceur qui les a achetés constitue tout ce que fait AdBubbles. AdBubbles n’a aucune prise sur qui voit une bulle, ne suit jamais un lecteur d’une page ou d’un site à l’autre, et ne promet aucun résultat. La position sur la confidentialité est publiée dans son intégralité.

Les navigateurs comptent désormais ce que coûte une publicité et agissent sur le total

L’intervention de Chrome contre les publicités lourdes montre ce qu’un éditeur de navigateur juge excessif. Une publicité n’est considérée comme lourde que « si l’utilisateur n’a pas interagi avec elle (par exemple, s’il ne l’a pas touchée ou n’a pas cliqué dessus) ».8 Au-delà, il suffit de franchir l’un de trois seuils. Le premier est plus de 4 mégaoctets de bande passante réseau. Le deuxième est plus de 15 secondes de temps sur le thread principal dans toute fenêtre de 30 secondes, et le troisième plus de 60 secondes au total.

Lorsque l’intervention se déclenche, le contenu du cadre publicitaire est « remplacé par un message Ad removed (publicité supprimée) », et le mécanisme agit sur les iframes marquées comme publicitaires.8 La mesure porte sur les octets et le temps sur le thread principal ; le contenu de la publicité n’y joue aucun rôle. Une bulle est affichée dans un Shadow DOM à l’intérieur du document de l’éditeur plutôt que dans une iframe : ce mécanisme vise donc un autre type de publicité. Ce que le script d’intégration ajoute à une page donnée, en octets et en temps sur le thread principal, les propres mesures de cette page le montreront.

La vérification qu’un éditeur peut faire sur sa propre page ne nécessite rien d’autre qu’un navigateur. Le code source de la page liste chaque élément script de l’en-tête, et chacun porte async ou defer, ou ne porte ni l’un ni l’autre. La section Opportunities (opportunités) de Lighthouse présente ceux qui n’en portent aucun comme des URL bloquant le premier affichage.4 L’extrait de code d’un réseau figurant dans cette liste bloque la page au sens de la norme, quoi qu’en dise la documentation du réseau sur son poids. Qu’un script publicitaire rejoigne cette liste dépend de l’attribut de son élément, et cet attribut est écrit dans l’extrait de code avant même qu’un éditeur ne le colle.