Le problème / Le besoin

Si vous avez déjà collé un <script> “vite fait” dans le header et qu’un jour un plugin de cache, un builder ou une mise à jour WordPress a tout cassé, vous avez déjà rencontré le vrai sujet : charger CSS et JS proprement.

Sur WordPress 6.9.4 (avril 2026), la manière correcte de charger vos fichiers est d’utiliser l’API d’enqueue : wp_enqueue_scripts côté front, et admin_enqueue_scripts côté administration. C’est plus fiable, plus maintenable, et ça évite une grande partie des conflits liés à l’ordre de chargement, aux dépendances et au cache.

Ce guide s’adresse aux blogueurs débutants (et à ceux qui bricolent des snippets) qui veulent :

  • charger un CSS et un JS sans casser le thème,
  • les charger seulement là où il faut (page précise, type de contenu, shortcode),
  • comprendre pourquoi “coller du code dans le header” est une mauvaise idée,
  • éviter les erreurs classiques (hook inadapté, mauvais chemin, cache, dépendances).

Où coller le code de cet article : idéalement dans un mini-plugin (recommandé) ou un mu-plugin. À défaut, dans le functions.php d’un thème enfant (pas le thème parent). Ne modifiez jamais WordPress (le core).

Fonctions WordPress que vous allez utiliser (avec doc officielle) :


Résumé rapide

  • Vous allez créer un petit plugin qui charge un CSS et un JS via wp_enqueue_scripts.
  • Vous allez déclarer des dépendances (ex. jquery) et une version pour mieux gérer le cache.
  • Vous allez charger les fichiers uniquement sur certaines pages (ex. page “Contact”) pour éviter d’alourdir tout le site.
  • Vous allez apprendre quand utiliser wp_add_inline_script() au lieu de coller un <script> dans le header.
  • Vous repartez avec une checklist de test + un tableau de diagnostic des pannes courantes.

Quand utiliser cette solution

  • Vous ajoutez un petit script (menu sticky, tracking maison, animation légère) et vous voulez qu’il survive aux mises à jour.
  • Vous avez un CSS “custom” que vous ne voulez pas coller dans l’interface du builder (ou dans le personnalisateur) pour garder une trace versionnée.
  • Vous devez charger une librairie (slider, lightbox) sur une page ou un type de contenu seulement.
  • Vous voulez éviter les conflits avec Divi 5 / Elementor / Avada et les plugins de cache qui réorganisent/minifient les scripts.

Quand ne PAS utiliser cette solution

Ne forcez pas du code si une solution native existe déjà :

  • CSS “petites retouches” : si c’est 10 lignes, le “CSS additionnel” du personnalisateur peut suffire. Mais dès que ça grossit, passez à un fichier enqueue.
  • Scripts de tracking (GA4, Matomo, Pixel) : utilisez un plugin de tracking fiable (ou Google Site Kit) plutôt que du code artisanal. Ça gère mieux le consentement et les changements d’API.
  • Code spécifique à un bloc Gutenberg : si vous développez un bloc, la bonne pratique est d’enregistrer les assets via block.json (build tooling) plutôt que via wp_enqueue_scripts. L’enqueue global reste valable, mais ce n’est pas le plus précis.
  • Vous travaillez sur un thème bloc (FSE) et vous voulez juste du style global : regardez aussi theme.json. Ce n’est pas un remplaçant du JS, mais ça évite beaucoup de CSS custom.

Prérequis / avant de commencer

Versions et environnement

  • WordPress : 6.9.4+
  • PHP : 8.1+ (recommandé)
  • Accès FTP/SFTP ou gestionnaire de fichiers (idéalement Git)
  • Un site de test (staging) ou une sauvegarde restaurable

Sauvegarde et sécurité

  • Faites une sauvegarde (fichiers + base de données) avant de toucher au code.
  • Ne modifiez jamais un thème parent : une mise à jour écrasera vos changements.
  • Évitez les plugins de “snippets” pour du JS/CSS complexe. J’ai souvent vu des sites tomber en écran blanc à cause d’un snippet mal copié, sans logs exploitables.

Outils utiles (optionnels mais pratiques)

  • Un plugin de logs (ou l’accès aux logs serveur) pour voir les erreurs PHP.
  • Un plugin de staging si votre hébergeur n’en propose pas.
  • Les DevTools du navigateur (onglet Network/Console) pour vérifier le chargement.

L’approche naïve (et pourquoi l’éviter)

La version “débutant pressé” ressemble souvent à ça : on colle du HTML dans le header via un champ du thème, un widget, ou un plugin qui injecte du code.

<!-- Exemple à NE PAS reproduire -->
<link rel="stylesheet" href="/wp-content/themes/mon-theme/assets/custom.css">
<script src="https://example.com/ma-lib.js"></script>
<script>
  // Code inline “vite fait”
  console.log('Hello');
</script>

Pourquoi ça pose problème (dans la vraie vie)

  • Ordre de chargement aléatoire : votre script peut s’exécuter avant jQuery, avant un script du builder, ou avant le DOM. Résultat : erreurs en console.
  • Dépendances non déclarées : WordPress ne sait pas que votre script dépend de jquery ou de wp-element. Vous perdez la gestion automatique.
  • Cache et minification : les plugins de performance regroupent/déplacent les scripts. Un <script> collé “en dur” échappe souvent à leurs règles, ou pire, est déplacé sans dépendances.
  • Maintenance : quand vous changez de thème (ou de header builder), votre code disparaît. Dans mon expérience, c’est la cause n°1 des “mon site a perdu ses scripts” après refonte.
  • Sécurité : injecter du JS via des champs admin peut ouvrir la porte à des XSS si plusieurs rôles ont accès à ces champs. Même si ce n’est “que vous”, ça finit souvent en “je donne l’accès à un rédacteur”.

La bonne approche — tutoriel pas à pas

Objectif : créer un petit plugin qui charge un CSS et un JS proprement, avec versioning, dépendances, et chargement conditionnel.

Étape 1 — Créez un mini-plugin (recommandé)

Créez un dossier : wp-content/plugins/bp-assets-loader/

Dans ce dossier, créez le fichier : bp-assets-loader.php

C’est ici que vous collez le code PHP (pas dans le header, pas dans un fichier du core).

Étape 2 — Ajoutez vos fichiers CSS/JS

Créez :

  • wp-content/plugins/bp-assets-loader/assets/css/bp-custom.css
  • wp-content/plugins/bp-assets-loader/assets/js/bp-custom.js

Étape 3 — Enqueue via le hook wp_enqueue_scripts

Définition : un hook (crochet) est un point d’extension. Une action exécute du code à un moment donné (ici : quand WordPress prépare les scripts/styles du front). Un filtre modifie une valeur et la renvoie.

Vous allez accrocher (hook) une fonction sur l’action wp_enqueue_scripts.

Étape 4 — Chargez seulement là où c’est utile

Exemple concret : vous ne voulez charger votre JS que sur la page “Contact”. C’est un gain de performance réel.

Vous pouvez cibler :

  • une page : is_page('contact') ou is_page(123)
  • un article : is_single()
  • un type de contenu : is_singular('product') (WooCommerce)
  • un template : is_page_template()

Étape 5 — Ajoutez du JS inline correctement (si nécessaire)

Si vous avez 5 lignes de configuration (une variable, un flag), ne collez pas un <script> dans le header. Utilisez wp_add_inline_script() attaché à votre handle. WordPress garantit ainsi l’ordre : inline après le script ciblé.


Code complet

Copiez-collez ce fichier dans wp-content/plugins/bp-assets-loader/bp-assets-loader.php, puis activez le plugin dans Extensions.

<?php
/**
 * Plugin Name: BP Assets Loader (CSS/JS propre)
 * Description: Exemple pédagogique : charger CSS/JS correctement via wp_enqueue_scripts (WordPress 6.9.4+).
 * Version: 1.0.0
 * Requires at least: 6.9
 * Requires PHP: 8.1
 * Author: Votre Nom
 */

declare(strict_types=1);

if (!defined('ABSPATH')) {
	exit; // Sécurité : empêche l'accès direct au fichier.
}

/**
 * Retourne une "version" basée sur la date de modification du fichier.
 * Pratique en dev pour casser le cache sans changer le numéro de version à la main.
 *
 * En prod, vous pouvez préférer une version fixe (ex: 1.0.0) pour maîtriser le cache.
 */
function bp_assets_loader_file_version(string $filepath): string {
	if (file_exists($filepath)) {
		return (string) filemtime($filepath);
	}
	return '1.0.0';
}

/**
 * Enqueue des assets front (site public).
 *
 * Hook : wp_enqueue_scripts
 * Doc : https://developer.wordpress.org/reference/hooks/wp_enqueue_scripts/
 */
function bp_assets_loader_enqueue_front(): void {

	// 1) Exemple de chargement conditionnel : on ne charge que sur la page "Contact".
	// Remplacez 'contact' par le slug de votre page, ou utilisez l'ID (ex: is_page(123)).
	if (!is_page('contact')) {
		return;
	}

	$plugin_url  = plugin_dir_url(__FILE__);
	$plugin_path = plugin_dir_path(__FILE__);

	$css_rel = 'assets/css/bp-custom.css';
	$js_rel  = 'assets/js/bp-custom.js';

	$css_file = $plugin_path . $css_rel;
	$js_file  = $plugin_path . $js_rel;

	$css_ver = bp_assets_loader_file_version($css_file);
	$js_ver  = bp_assets_loader_file_version($js_file);

	// 2) Charger le CSS.
	// wp_enqueue_style( $handle, $src, $deps, $ver, $media )
	// Doc : https://developer.wordpress.org/reference/functions/wp_enqueue_style/
	wp_enqueue_style(
		'bp-custom-css',
		$plugin_url . $css_rel,
		array(),      // Dépendances CSS (souvent vide).
		$css_ver,
		'all'
	);

	// 3) Charger le JS.
	// wp_enqueue_script( $handle, $src, $deps, $ver, $args )
	// Doc : https://developer.wordpress.org/reference/functions/wp_enqueue_script/
	//
	// Astuce : $args peut être un bool (in_footer) ou un tableau.
	// Ici, on utilise un tableau pour être explicite.
	wp_enqueue_script(
		'bp-custom-js',
		$plugin_url . $js_rel,
		array(), // Dépendances : ajoutez 'jquery' si votre code dépend de jQuery.
		$js_ver,
		array(
			'in_footer' => true,  // Charge en bas de page : souvent meilleur pour les perfs.
			'strategy'  => 'defer' // Demande à WP d'ajouter defer si possible.
		)
	);

	// 4) Exemple de configuration JS inline (propre).
	// On évite de coller un <script> dans le header.
	// Doc : https://developer.wordpress.org/reference/functions/wp_add_inline_script/
	$config = array(
		'ajaxUrl' => admin_url('admin-ajax.php'),
		'isDebug' => defined('WP_DEBUG') && WP_DEBUG,
	);

	// wp_json_encode assure un JSON valide.
	$inline = 'window.BP_CUSTOM = ' . wp_json_encode($config) . ';';

	// Le code inline sera placé APRÈS le script 'bp-custom-js'.
	wp_add_inline_script('bp-custom-js', $inline, 'after');
}
add_action('wp_enqueue_scripts', 'bp_assets_loader_enqueue_front', 20);

Ajoutez ensuite un CSS minimal :

/* Fichier : assets/css/bp-custom.css */
.bp-contact-highlight {
  border: 2px solid #1e1e1e;
  padding: 12px;
}

Et un JS minimal :

// Fichier : assets/js/bp-custom.js
(function () {
  // Exemple : vérifie que la config inline est présente
  if (window.BP_CUSTOM && window.BP_CUSTOM.isDebug) {
    console.log('BP_CUSTOM config:', window.BP_CUSTOM);
  }

  // Exemple : ajoute une classe sur un élément (à adapter à votre thème/builder)
  var el = document.querySelector('.wpcf7'); // Contact Form 7, par exemple
  if (el) {
    el.classList.add('bp-contact-highlight');
  }
})();

Explication du code

Explication simple (ce qui se passe)

  • WordPress arrive au moment où il prépare les scripts/styles du front.
  • Votre fonction bp_assets_loader_enqueue_front() s’exécute grâce à add_action().
  • Elle vérifie si on est sur la page “Contact”. Si non : elle ne charge rien.
  • Si oui : elle charge bp-custom.css et bp-custom.js avec une version basée sur la date de modification du fichier.
  • Elle injecte une petite config JS via wp_add_inline_script(), au bon endroit, sans bricolage dans le header.

Explication technique (les détails qui évitent les bugs)

add_action('wp_enqueue_scripts', ...) : vous accrochez une fonction sur une action. L’action wp_enqueue_scripts est le moment standard pour enqueuer côté front. Doc : add_action().

Priorité 20 : j’utilise souvent 20 (au lieu de 10) sur des sites avec builders/caches, parce que certains thèmes enqueuent beaucoup de choses à 10. Ça ne règle pas tout, mais ça réduit certains cas où votre style est immédiatement “écrasé” par un style chargé après.

plugin_dir_url(__FILE__) et plugin_dir_path(__FILE__) : évite les chemins codés en dur. Si vous migrez de domaine, de sous-dossier, ou si vous changez de structure, ça continue de fonctionner.

Versioning via filemtime() : WordPress ajoute ?ver=.... Les caches (navigateur/CDN) peuvent alors distinguer une nouvelle version. Doc PHP : filemtime().

strategy => defer : WordPress peut ajouter defer au script, ce qui retarde l’exécution jusqu’après le parsing HTML. Ça réduit les blocages. Si un plugin de cache réécrit les scripts, testez : certains cassent le defer sur des scripts dépendants. Référence : wp_enqueue_script().

Inline via wp_add_inline_script() : vous gardez l’ordre garanti. L’inline est attaché à un handle, donc s’il est désactivé (par condition), l’inline ne sort pas non plus. C’est exactement ce que vous voulez.

Pourquoi “ne jamais coller un script dans le header” (version terrain)

  • Vous perdez le contrôle des dépendances et de l’ordre.
  • Vous vous exposez à des doubles chargements (ex. deux fois la même librairie).
  • Vous rendez le debug plus pénible : “ce script vient d’où ?” devient une chasse au trésor.
  • Vous augmentez le risque de XSS si ce code est éditable via l’admin par plusieurs rôles.

Variantes et cas d’usage

Variante 1 — Charger partout, mais seulement si l’utilisateur est connecté

Pratique pour un outil de debug visuel réservé à vous.

function bp_assets_loader_enqueue_for_logged_in(): void {
	if (!is_user_logged_in()) {
		return;
	}

	wp_enqueue_style(
		'bp-debug-css',
		plugin_dir_url(__FILE__) . 'assets/css/bp-debug.css',
		array(),
		'1.0.0'
	);
}
add_action('wp_enqueue_scripts', 'bp_assets_loader_enqueue_for_logged_in', 20);

Variante 2 — Déclarer une dépendance à jQuery (si vous en avez vraiment besoin)

En 2026, je conseille de viser du JS “vanilla” quand c’est possible. Mais certains scripts legacy utilisent jQuery.

wp_enqueue_script(
	'bp-custom-js',
	$plugin_url . $js_rel,
	array('jquery'), // Dépendance déclarée
	$js_ver,
	array(
		'in_footer' => true,
		'strategy'  => 'defer',
	)
);

Variante 3 — Charger un script uniquement quand un shortcode est présent

Cas fréquent : vous avez un shortcode [bp_map] et vous voulez charger la librairie de carte seulement quand il apparaît.

Approche simple : détecter la présence dans le contenu du post courant. Attention : si votre builder n’utilise pas le contenu WP classique, cette méthode peut échouer (voir section compatibilité builders).

function bp_assets_loader_enqueue_when_shortcode(): void {
	if (!is_singular()) {
		return;
	}

	global $post;
	if (!$post instanceof WP_Post) {
		return;
	}

	if (!has_shortcode($post->post_content, 'bp_map')) {
		return;
	}

	wp_enqueue_script(
		'bp-map-js',
		plugin_dir_url(__FILE__) . 'assets/js/bp-map.js',
		array(),
		'1.0.0',
		array('in_footer' => true)
	);
}
add_action('wp_enqueue_scripts', 'bp_assets_loader_enqueue_when_shortcode', 20);

Compatibilité Divi 5 / Elementor / Avada

Divi 5

Divi peut générer du contenu via son propre rendu. Deux points que je vois souvent :

  • La détection de shortcode via has_shortcode() peut être insuffisante si le contenu est stocké différemment.
  • Divi peut optimiser/minifier et changer l’ordre des scripts.

Conseil pratique : privilégiez les conditions basées sur la page (slug/ID) plutôt que sur le contenu, quand c’est un site 100% builder.

Elementor

Elementor charge déjà beaucoup d’assets. Pour éviter d’alourdir :

  • chargez votre CSS/JS seulement sur les pages concernées (is_page()),
  • utilisez defer et testez la console,
  • évitez de charger une seconde fois une librairie déjà fournie par Elementor.

Si vous devez absolument charger un script uniquement quand un widget Elementor est présent, le plus fiable est souvent de lier votre asset à un template/page précise, ou d’implémenter un petit plugin Elementor (niveau plus avancé).

Avada (Fusion Builder)

Avada a ses propres optimisations et peut concaténer des scripts. J’ai souvent vu :

  • un script chargé “en dur” dans le header qui se retrouve exécuté avant le HTML et échoue,
  • des scripts déplacés en footer sans dépendances correctes.

Avec l’enqueue WordPress, vous gardez une base propre. Si Avada “optimise trop”, désactivez temporairement ses options de performance pour isoler le problème, puis réactivez une à une.


Vérifications après mise en place

Checklist rapide

  • La page ciblée (ex. “Contact”) charge bien vos fichiers : ouvrez DevTools > Network > filtrez par “bp-custom”.
  • Votre CSS s’applique : vérifiez dans l’inspecteur que la règle vient bien de bp-custom.css.
  • Votre JS s’exécute : regardez la console (le console.log en mode debug).
  • Le script est bien en bas de page : “View Source” ou onglet Elements, cherchez bp-custom.js.
  • Après modification d’un fichier, la query string ?ver=... change (si vous utilisez filemtime).

Tableau de diagnostic (symptômes fréquents)

Symptôme Cause probable Vérification Solution
Le CSS/JS ne se charge pas du tout Plugin non activé, mauvais chemin, condition is_page() fausse WP Admin > Extensions, DevTools > Network Activez le plugin, vérifiez slug/ID, vérifiez assets/ et les noms de fichiers
Le fichier est en 404 Chemin incorrect, fichier manquant, mauvaise casse (Linux) Ouvrez l’URL du fichier dans le navigateur Corrigez le chemin, renommez correctement, vérifiez la casse
Le JS se charge mais “ne fait rien” Sélecteur DOM incorrect, script exécuté trop tôt Console : erreurs, testez document.querySelector Corrigez le sélecteur, utilisez defer ou attendez DOMContentLoaded si nécessaire
Après modification, rien ne change Cache navigateur/CDN/plugin DevTools > Disable cache, test en navigation privée Videz cache plugin/CDN, force refresh, vérifiez version ?ver=
Erreur console “$ is not defined” jQuery non chargé, ou script en defer mal géré Console, vérifiez dépendance jquery Ajoutez array('jquery') et adaptez votre code jQuery

Si ça ne marche pas

1) Vérifiez l’endroit où vous avez collé le code

  • Si vous l’avez mis dans un thème parent : mauvaise idée, déplacez-le dans un thème enfant ou un plugin.
  • Si vous l’avez collé dans un plugin de snippets : exportez-le vers un vrai plugin. Les snippets cassent souvent sur une simple parenthèse oubliée.

2) Activez le debug proprement (sur staging)

Sur un site de test, activez les logs WP si vous savez ce que vous faites. Référence : Debugging in WordPress.

3) Inspectez Network et Console

  • Network : votre fichier est-il chargé (200) ou absent (404) ?
  • Console : voyez-vous une erreur JS bloquante ?

4) Désactivez temporairement l’optimisation

Désactivez temporairement :

  • minification/concat JS,
  • defer/delay JS,
  • optimisation CSS.

J’ai souvent vu un script parfaitement enqueued être cassé par une option “Delay all JS” trop agressive.

5) Testez sans condition

Pour isoler, commentez temporairement le bloc if (!is_page('contact')) return; et vérifiez si l’asset apparaît partout. Si oui, votre problème est la condition (slug/ID, page traduite, page builder, etc.).


Pièges et erreurs courantes

Erreur Cause Solution
Coller le code dans header.php On suit un vieux tutoriel, ou on “teste vite” Utilisez wp_enqueue_scripts + un plugin/thème enfant
Écran blanc après ajout du code Point-virgule manquant, accolade en trop, PHP incompatible Vérifiez les logs, revenez en arrière via FTP, assurez PHP 8.1+
Utiliser le mauvais hook (init au lieu de wp_enqueue_scripts) Confusion entre moments d’exécution Enqueue front : wp_enqueue_scripts. Admin : admin_enqueue_scripts
Le CSS est chargé mais ne s’applique pas Spécificité CSS, ordre de chargement, CSS du builder plus fort Chargez plus tard (priorité 20), augmentez la spécificité, évitez !important systématique
Le JS ne se charge que parfois Cache, optimisation, condition trop stricte Videz cache, testez sans condition, vérifiez le slug/ID
“Call to undefined function …” Code exécuté trop tôt, ou fichier inclus au mauvais endroit Gardez l’enqueue dans le hook, ne lancez pas de fonctions WP hors contexte
Copier un snippet ancien incompatible Tutoriel pré-2020, paramètres obsolètes, mauvaises pratiques Référez-vous à la doc officielle WP 6.9+, utilisez wp_add_inline_script

Conseils sécurité, performance et maintenance

Sécurité

  • Évitez les champs d’injection de scripts accessibles à des rôles non-admin. C’est un classique des XSS.
  • Si votre JS consomme des données PHP, ne concaténez pas des chaînes “à la main”. Utilisez wp_json_encode() (comme dans l’exemple) et échappez côté sortie quand vous générez du HTML.

Performance

  • Chargez vos assets uniquement là où ils servent. C’est le gain le plus simple.
  • Préférez un fichier JS dédié plutôt que 30 lignes inline dans le header : c’est mieux cacheable.
  • Utilisez une version stable en production (ex. 1.0.3) si vous avez un CDN agressif. filemtime() est top en dev, mais peut multiplier les variations si vous déployez souvent.

Maintenance

  • Donnez des handles clairs : bp-custom-js plutôt que script1. Vous vous remercierez le jour où vous devrez “dequeuer” un asset.
  • Centralisez vos assets dans un plugin si vous changez souvent de thème. C’est un pattern que j’applique sur beaucoup de sites éditoriaux : le thème gère le design, le plugin gère les comportements transverses.

Ressources


FAQ

Est-ce que je peux mettre ce code dans functions.php ?

Oui, mais uniquement dans le functions.php d’un thème enfant. Si vous changez de thème, vous perdrez ce code. Pour un site amené à évoluer, le mini-plugin est plus robuste.

Pourquoi mon CSS se charge mais n’écrase pas celui du thème/builder ?

Souvent, c’est un mélange d’ordre de chargement et de spécificité CSS. Chargez votre CSS plus tard (priorité 20), puis ajustez vos sélecteurs. Évitez de mettre !important partout : ça rend la maintenance pénible.

Mon script a besoin de jQuery : je fais comment ?

Déclarez la dépendance array('jquery') dans wp_enqueue_script(). Ensuite, écrivez votre code jQuery correctement (en évitant de supposer que $ est global).

Pourquoi mon JS ne s’exécute pas avec defer ?

defer change le moment d’exécution. Si votre script dépend d’un autre script non defer, ou si un plugin de cache réécrit tout, vous pouvez avoir un ordre inattendu. Testez sans strategy, puis réactivez progressivement.

Puis-je ajouter du JS inline quand même ?

Oui, mais via wp_add_inline_script() (ou wp_add_inline_style() pour le CSS). Ça garde l’ordre et la traçabilité.

Comment charger un script seulement sur une page créée avec un builder ?

Le plus fiable est de cibler la page par ID/slug (is_page()). La détection “le contenu contient X” est moins fiable avec Divi/Elementor/Avada.

Pourquoi mon fichier est en 404 alors que le chemin “a l’air bon” ?

Sur beaucoup d’hébergements Linux, la casse compte : custom.js et Custom.js sont deux fichiers différents. Vérifiez aussi que le fichier est bien envoyé sur le serveur.

Mon site ne reflète pas mes changements, même avec filemtime()

Regardez côté CDN (Cloudflare, etc.) et côté plugin de cache. Testez en navigation privée et cochez “Disable cache” dans DevTools. Videz ensuite le cache serveur/CDN.

Est-ce que ça marche avec un thème bloc (FSE) ?

Oui. wp_enqueue_scripts reste valable. Pour des styles purement “design system”, theme.json est souvent plus adapté, mais ça ne remplace pas le chargement de JS.

Je peux charger un script externe (CDN) avec wp_enqueue_script ?

Oui : mettez l’URL complète en $src. Vérifiez la politique de confidentialité/consentement si c’est un script de tracking, et testez les blocages (adblockers, CSP).