← Dossiers · Plugin WordPress

Créer une solution de synchro ATS vers Google for Jobs en plugin WordPress

Un plugin sur mesure livré en 20 jours, qui a remplacé une solution SaaS du marché et rattrapé 50 % de chiffre d'affaires perdu en un mois.

Client Un cabinet de recrutement spécialisé en métiers comptables du BTP · Recrutement BtoB Anonymisé

Publié le

Tags #wordpress #google-for-jobs #eolia #seo #http-410 #schema-org

Là où une solution SaaS du marché a mis un an pour livrer un résultat qui a fait perdre 50 % de chiffre d’affaires au client en six mois, un plugin sur mesure développé seul en 20 jours a remis le SEO sur les rails et rattrapé le manque à gagner en quelques semaines.

Le contexte

Un cabinet de recrutement spécialisé sur un créneau précis — les métiers comptables et financiers du BTP — autour de six à huit collaborateurs. Site WordPress, environ 1 200 offres d’emploi en moyenne sur le site à un instant T, avec une page reine en SEO local positionnée en top 5 sur les requêtes du type cabinet recrutement [ville].

Le problème — l’histoire en deux temps

Premier temps : l’avertissement

Le client utilisait jusque-là un plugin WordPress officiel fourni par son éditeur d’ATS — solution qui fonctionnait sur le domaine principal, sans dépendance externe. Il signe avec un autre éditeur SaaS RH bien installé pour publier les offres sur une plateforme propriétaire hébergée sur un sous-domaine. Première rencontre avec moi à ce moment-là : audit gratuit, plusieurs red flags identifiés.

  • Les offres sont migrées sur un sous-domaine dédié à l’éditeur (du genre jobs.client.fr) au lieu d’être servies sur le domaine principal. Toute l’autorité SEO accumulée pendant des années sur le domaine principal n’est plus mobilisée pour les pages d’offres.
  • La qualité du code rendu sur le sous-domaine pose problème : balisage JobPosting schema.org partiellement implémenté, métadonnées approximatives, performances dégradées.
  • Aucune passerelle SEO entre l’ancien et le nouveau périmètre : pas de redirections propres, pas de canonicals.

L’avertissement est posé par écrit. Le contrat venait d’être signé, l’engagement court sur 12 mois. Réponse du dirigeant : je suis engagé, je vais surveiller sur les prochains mois.

Deuxième temps : la chute

L’inertie SEO masque le problème pendant deux mois. Septembre et octobre 2025 affichent encore environ 1 000 clics mensuels en Search Console — un résiduel des positions historiques sur les offres déjà indexées.

Puis la donnée bascule.

Les chiffres qui suivent proviennent de Google Search Console : ils mesurent uniquement les clics depuis les résultats de recherche organique de Google, pas l’ensemble du trafic du site. Le trafic global d’un site agrège aussi les accès directs, les réseaux sociaux, les autres moteurs de recherche, les referrals, et le payant — autant de sources que Search Console n’observe pas. Ce que ces chiffres racontent, c’est la santé du référencement naturel sur Google, c’est-à-dire la principale source de prospects entrants pour un cabinet de recrutement.

MoisClics SEOPosition moyenne
Octobre 20251 00014.6
Novembre 202562215.8
Décembre 202542815.0
Janvier 202682015.7
Février 202677813.0

Décembre 2025 : 428 clics sur le mois, soit −57 % vs octobre. En parallèle, le dirigeant constate côté business environ 50 % de chiffre d’affaires perdu sur le trimestre. Les nouveaux mandats ne rentrent plus, les positions Google sur les requêtes locales se sont effondrées.

Diagnostic en arrière-plan : la Search Console est polluée par environ 20 000 URLs orphelines générées par le sous-domaine de l’éditeur SaaS. Ces URLs aspirent tout le budget de crawl Google, qui n’a plus de bande passante pour réexplorer les pages utiles du domaine principal. Le SEO du domaine ne s’effondre pas seul — il étouffe sous le poids des URLs poubelles de l’ATS hébergé externe.

Troisième temps : la commande

Le client rompt l’engagement avec l’éditeur SaaS, négocie une sortie anticipée, revient me voir. Le brief tient en quelques lignes : un plugin WordPress qui fait le travail mieux, hébergé sur le domaine principal, sans dépendance externe, sans sous-domaine, et qui répare ce que la précédente solution a abîmé.

L’approche technique

L’architecture vise l’autonomie. Le plugin doit fonctionner sans dépendre de Yoast, RankMath ou d’un autre plugin SEO. Il doit aussi s’effacer proprement s’il en détecte un, sans conflit.

Le contenu : un CPT taillé pour schema.org

Custom Post Type eolia_job avec metaboxes structurées. Le balisage JobPosting de schema.org est respecté à 100 % pour passer les rich results de Google et permettre l’indexation par Google for Jobs : datePosted, validThrough, employmentType, hiringOrganization, jobLocation, baseSalary (quand l’information est disponible), identifier. Toute imprécision sur ce balisage et Google déclasse silencieusement la page.

La synchronisation depuis l’ATS Eolia

Eolia est un logiciel ATS français utilisé par de nombreux cabinets de recrutement. Il expose un flux XML public et configurable. Le plugin fait :

  • Fetch périodique du flux XML, contrôlé par un cron interne plutôt que wp_cron
  • Dédoublonnage par identifiant d’offre côté Eolia, stocké en post meta
  • Création / mise à jour / désactivation des offres selon les changements observés dans le flux
  • Lock TTL 20 minutes pour éviter qu’un fetch déclenché manuellement ne percute un fetch planifié

Le piège qui a coûté une demi-journée à diagnostiquer : l’hébergement client tourne sur IONOS/Plesk avec DISABLE_WP_CRON=true activé pour des raisons de performance. wp_cron ne tourne donc pas du tout, et spawn_cron() ne fait rien. Solution propre : appel direct à sync_jobs() depuis le bouton de synchronisation manuelle et depuis un cron système configuré côté hébergeur, sans passer par les mécanismes WordPress.

Le grand nettoyage : HTTP 410 pour les URLs orphelines

Faire revenir 815 URLs en 404 n’est pas la bonne réponse. Google met des mois à digérer des 404 — il les revisite, les considère comme temporaires, garde l’URL en index. La bonne réponse est HTTP 410 Gone : un signal fort et permanent que la ressource a été retirée.

Implémentation :

  • Table custom wp_eolia_deleted_jobs pour mémoriser la liste des URLs à servir en 410. Séparée de postmeta qui était déjà sursollicitée sur ce site.
  • Admin custom avec import CSV en dry-run pour valider avant exécution, puis traitement AJAX par lots de 50 URLs pour éviter le timeout côté serveur.
  • Sitemap dédié /sitemap-eolia-deleted-jobs.xml enregistré via parse_request priorité 1, listant les 410. Google a besoin de pouvoir crawler ces URLs pour intégrer leur statut de retrait — un 410 sans visibilité dans un sitemap n’est jamais consommé.
  • Page 410 standalone (sans Yoast, sans theme), HTML minimal, header explicite Status: 410 Gone.

Le rythme de digestion est celui de Google, pas le mien. Compter 6 à 10 semaines pour que les URLs disparaissent de l’index, et donc que le budget crawl se libère pour les pages utiles.

Anti-pollution paramétrique

Quelques précautions au passage :

  • noindex sur les feeds Indeed et les paginations paramétriques type /q/, /page/2/, qui génèrent des doublons sans valeur.
  • Redirection 301 des ?job=indeed vers le permalink SEO de l’offre.
  • Proxy feed eolia-indeed-feed.xml qui sert les permalinks SEO à Indeed, plutôt que de laisser Indeed pointer vers des URLs paramétrées non SEO.

Compatibilité multi-plugins SEO

Le plugin fonctionne avec ou sans plugin SEO tiers. Si Yoast ou RankMath est actif, le plugin détecte et passe la main pour les sitemaps, en exposant simplement les CPT à indexer. Si aucun plugin SEO n’est présent, le sitemap interne est généré.

Un point de friction observé sur ce projet : Yoast tentait d’imposer ses balises Open Graph et son canonical sur le CPT eolia_job, avec des valeurs incorrectes (template générique au lieu des données structurées de l’offre). Résolu via les filtres wpseo_opengraph_* à priorité 99, qui reprennent la main pour réécrire proprement OG et canonical en fin de chaîne.

Google Indexing API

L’API Indexing de Google permet de notifier des changements d’URL en quasi temps réel — un fort levier d’accélération pour des contenus à durée de vie courte comme les offres d’emploi. Implémentation OAuth2 avec service account, gestion du quota quotidien, dédoublonnage des envois via post meta pour ne pas claquer le quota en double notification.

En toute transparence : l’API Indexing pour JobPosting requiert une activation sur dossier auprès de Google. La demande a été déposée côté client mais n’a pas encore été instruite. Le plugin est prêt à exploiter l’API dès activation. C’est la seule dépendance externe qui n’a pas pu être résolue par le code seul.

La mise en œuvre

20 jours-homme en solo, du brief à la mise en production.

Le client avait perdu un an et 50 % de son chiffre d’affaires avec la solution SaaS. La même fonctionnalité, livrée avec une compréhension du contexte SEO du client, a pris 20 jours. Ce n’est pas une question d’outil ou d’IA — c’est une question d’avoir intégré le métier du recrutement, le fonctionnement de Google for Jobs et les contraintes WordPress avant de coder.

En parallèle du plugin, refonte légère du site, refonte du maillage interne, optimisation PageSpeed Insights, retravail des pages SEO locales. La plomberie marche, mais sur un site qui tient la route.

Résultats mesurables

Sur 16 mois de données Search Console, l’arc complet de l’histoire est lisible.

PériodeClics mensuels moyensPosition moyenne
Premier semestre 2025 (avant SaaS)69029.5
Période SaaS (sept 25 → fév 26)77015.6
Creux de décembre 202542815.0
Après bascule plugin (mars → mai 26)9908.5
Mars 2026 — premier mois plein1 2207.7

Trois lectures :

  • Trafic SEO mensuel : +28 % par rapport à la période SaaS, et record absolu en mars 2026 sur les 16 mois observés
  • Position moyenne : divisée par deux (15.6 → 8.5), passage du milieu de page 2 vers le bas du top 10
  • Inertie de retour : la remontée se fait en six semaines, pas en six mois. La libération du budget crawl par le retrait des 20 000 URLs orphelines fait le travail à mesure que Google les digère.

Côté business côté client : le chiffre d’affaires perdu est rattrapé en environ un mois. Des prospects que le cabinet démarchait depuis cinq ou six ans sans réponse sont revenus signer, attirés par la qualité revisitée du site et la visibilité retrouvée sur les requêtes locales.

Leçons à reprendre

1. L’inertie SEO masque les problèmes — dans les deux sens. Une dégradation d’architecture met deux à trois mois à se voir dans la donnée Search Console. À l’inverse, une réparation propre met quatre à huit semaines à porter ses fruits. Ne pas se laisser rassurer par les chiffres immédiats post-déploiement d’un SaaS, ni s’effondrer si la remontée semble lente après réparation. La donnée raconte la vérité, mais avec un décalage.

2. Sous-domaine pour les offres d’emploi = piège quasi systématique. Quand un éditeur SaaS RH propose d’héberger les offres sur son propre sous-domaine, il propose de récupérer l’autorité SEO de votre domaine vers le sien, en échange d’un confort opérationnel. Maintenir tout sur le domaine principal demande plus de travail à l’éditeur — ce qui explique souvent pourquoi il ne le propose pas. C’est presque toujours la bonne décision côté client.

3. L’IA dans un workflow ne remplace pas l’expertise métier. Brancher Claude ou n’importe quel LLM dans un produit ne sert que dans la mesure de ce qu’on comprend du domaine cible. Un plugin SEO mal pensé reste mauvais même augmenté à l’IA. Une intégration IA utile suppose qu’on maîtrise déjà ce qu’on automatise. L’IA ne sert ou ne dessert son propriétaire qu’à hauteur de ses connaissances et de son expérience.

Pour aller plus loin