50 jours de SEO en B2B nettoyage : 194 pages dans Yandex et +86 % de clics GSC
50 jours ouvrés depuis le relancement du site : 194 pages indexées dans Yandex, +86 % de clics GSC, Lighthouse 93/100. Zéro lien payant, zéro agence.
Le 22 mars 2026, j’ai lancé un nouveau site pour l’entreprise de propreté où je travaille comme directeur marketing en interne. 50 jours ouvrés plus tard : 194 pages dans l’index Yandex, +86 % de clics et +90 % d’impressions d’un mois sur l’autre dans Google Search Console, Lighthouse Performance 93/100 sur mobile, CLS 0,002. Zéro lien payant, zéro agence, zéro prestataire. Site PHP 8.4 fait maison, 245 URLs dans le sitemap.
En bref
- 245 URLs en 50 jours : 51 services, 18 quartiers de Saint-Pétersbourg, 70 stations de métro, 12 villes satellites, 50+ articles de blog.
- 194 pages en Yandex Searchable. Au départ le 13 avril : 111. Au 5 mai : 194-201 (ça oscille).
- 92 pages récupérées de l’état ‘Excluded by noindex’ via recrawl API + IndexNow + lastmod.
- +86 % de clics GSC et +90 % d’impressions d’un mois sur l’autre (52 → 97 clics, 2 826 → 5 359 impressions).
- Lighthouse mobile : Performance 93, SEO 100, CLS 0, LCP 2,4 s, TBT 60 ms.
- SEO Health Score interne : 62 → 84 en 18 jours.
Ci-dessous, semaine par semaine : ce que j’ai fait, quelles corrections ont vraiment bougé les chiffres, et là où j’ai trébuché.
Le point de départ, 22 mars
22 mars, c’était l’initial commit d’un projet PHP vide fait maison. Pas de CMS, pas de build pipeline, pas de node_modules. Six pages système (accueil, tarifs, à propos, contacts, licences, confidentialité) et 18 pages services. Le reste, devant moi.
J’ai choisi une stack volontairement simple :
- PHP 8.4 sur hébergement mutualisé, sans CMS
.htaccessen routeur, pattern/uborka-metro-{slug}/→uborka-metro-{slug}.php- MySQL pour le blog, les leads et l’AggregateRating dynamique
- CSS directement dans le repo, JS vanilla, pas de bundler, pas de transpileur
- Inter auto-hébergé (woff2), pas de Google Fonts
Pourquoi cette stack. L’entreprise avait déjà un site - vieux et lourd. Je ne pouvais pas me permettre une migration de six mois vers une ‘stack moderne’. Il me fallait un démarrage rapide, le contrôle de chaque octet du markup, et la capacité à corriger le schema sans bataille avec les plugins CMS. Le PHP fait maison couvre les trois, et sert du HTML en millisecondes.
Semaine par semaine
Semaines 1-2 : technique et formulaires
Première chose : l’anti-spam des formulaires. Six filtres, sans captcha : un honeypot <input name="website" style="display:none">, regex pour URLs dans le commentaire, longueur du téléphone entre 10 et 11 chiffres, ratio de non-cyrillique sur les commentaires de plus de 5 caractères, rate-limit à 5 requêtes par heure par IP, log dans un spam_log.txt protégé. Le captcha ajoute +5 de friction utilisateur ; ces filtres bloquent 99 % du spam sans captcha.
Ensuite CSP avec une whitelist pour GA4, Yandex Metrica, Roistat, AmoCRM, Beget CDN. HSTS preload, Referrer-Policy, X-Frame-Options. Tokens CSRF sur chaque POST.
Toute l’analytics enveloppée dans requestIdleCallback(fn, {timeout: 3000}) - GA4, Metrica et Roistat ne bloquent pas le rendu. Le preconnect pour l’analytics n’a pas marché - la connexion expirait avant utilisation, gâchant des ressources. dns-prefetch a suffi.
À la fin de la semaine 2 : Inter auto-hébergé avec @font-face size-adjust: 107%; ascent-override: 90% basé sur Arial - a tué le décalage FOUT qui rongeait le CLS.
Semaine 3 : premier audit, cartographie du site
5 avril : premier audit SEO complet via 7 sous-audits parallèles : contenu / E-E-A-T, technique SEO, on-page, schema, Core Web Vitals, AI Search Readiness, images. Pondérations : 23/22/20/10/10/10/5 %. Score 62/100. Principaux trous : schema (LocalBusiness dupliqué sur 30+ pages), CLS 0,377, XSS inline dans js/main.js, mot de passe admin en MD5.
Au 8 avril, tout fermé : un bloc LocalBusiness multi-type avec @id dans le footer, les pages référencent par @id au lieu de répéter ; CLS 0,377 → 0,002 en une journée ; XSS corrigé via createElement + textContent ; mot de passe admin passé en SHA-256 + salt. Au 10 avril, score 72.
En parallèle, passage du site dans Screaming Frog, 474 URLs trouvées : 245 utiles, le reste des versions obsolètes et des stubs de templates. 43 pages métros avec contenu mince (~230 mots) retirées du sitemap.
Semaine 4 : Programmatic SEO - 100 pages
À partir du 16 avril, journée programmatic : j’ai rempli 39 stations de métro + 18 quartiers + 12 villes satellites avec du contenu unique. Un template, du contenu unique - $district_content, $metro_content, $city_content injectés dans metro-template.php, district-template.php, lo-template.php partagés. Seuil d’unicité par page : au-dessus de 45 %, vérifié via Screaming Frog Near Duplicates.
Pour éviter le risque doorway, chaque page a :
- Un H1 et H2 uniques (pas de phrases template style ‘Nettoyage dans le quartier X’)
- Une section ‘Spécificités locales’ de 200 à 300 mots sur le quartier ou le métro
- 3-5 FAQ spécifiques à la localisation
- Tarifs, délai d’intervention de l’équipe, adresse du site actif le plus proche
Mon Programmatic SEO Score interne est ressorti à 95/100. C’est sur le template, pas sur le ranking réel - ça je vérifierai dans les impressions GSC dans 3-4 mois.
Semaine 5 : vague blog
9 avril : vague une, 21 articles publiés en une journée. 17 avril : vague deux, 10 de plus. Fin avril, 50+ articles dans le blog, 1 500 à 4 000 mots chacun, chacun avec :
- Schema BlogPosting + FAQPage + QAPage
- 4-5 questions FAQ, vraies requêtes tirées de Wordstat et People Also Ask
- 3+ liens internes : un vers un service, un vers un autre article, un vers /price/ ou contacts
- Un Author Person avec
rel="author"sur dimaserbun.ru - Une bannière Pexels (licence libre), plus une version JPEG séparée pour Yandex Zen
Cadence après les deux vagues : 2-3 articles par semaine. Pas plus de 5 par jour, et pas de backdating de 50 articles sur un mois - ça crame les templates de filtres des moteurs. Le 6 mai j’ai redistribué 11 posts prêts sur la plage 20-30 avril pour que la densité de publication paraisse régulière.
Semaine 6 : citabilité IA et récupération Excluded
24-26 avril, trois chantiers en parallèle.
Récupération des Excluded. 13 avril : 56 pages en Excluded sur Yandex. 22 avril : 92. La moitié du site. Via Yandex Webmaster API → /recrawl/queue j’ai envoyé 37 articles de blog en recrawl (quota : 620 URLs par jour) plus IndexNow ping pour 70 URLs métro. Au 5 mai : 1 page restante en Excluded sur 93. La plupart sont revenues en Searchable, maintenant 194-201.
Audit GEO et AI Overviews. Scores par plateforme : Google AIO 58, ChatGPT web search 48, Perplexity 62, Bing Copilot 64. Total 61/100. Principales corrections : passages de 134 à 167 mots sous H2 sur 5 pages clés, avec la réponse directe dans les 40 à 50 premiers mots + classe .answer-block pour speakable ; H2 reformulés en questions (‘Quel nettoyage convient à votre type d’appartement ?’ au lieu de ‘Nettoyage par type d’appartement’) ; crawlers IA autorisés dans robots.txt - GPTBot, OAI-SearchBot, ClaudeBot, anthropic-ai, Google-Extended, PerplexityBot, CCBot, YouBot, cohere-ai, Bytespider, meta-externalagent. Plus llms.txt à la racine du site au format llmstxt.org - H1, blockquote de description, sections H2 avec listes, immatriculation / ISO / notes.
Glossaire. 26 avril : page /glossary/ avec 45 termes du nettoyage + schema DefinedTermSet. Maillage interne - 188 liens vers /glossary/#anchor depuis le corps des pages - ça envoie un signal structurel ‘ce site a son propre vocabulaire’ et ouvre la voie aux citations IA.
Semaine 7 : niveau A et B, expansion des templates
5 mai : pack confiance et YMYL.
Niveau A (confiance) : preconnect vers le domaine CDN, preload mobile de l’image hero, AggregateRating dynamique depuis MySQL dans le schema, tableau AreaServed de 31 villes (18 quartiers de Saint-Pétersbourg + 12 oblast de Leningrad + Saint-Pétersbourg). Retrait des marques du corps des pages quand elles n’étaient pas strictement factuelles - Karcher, Koch Chemie, autres - gardées seulement où elles sont de vrais faits produits.
Niveau B (YMYL) : sur les pages nettoyage après décès et nettoyage post-incendie - liens vers la licence Rospotrebnadzor, SanPiN 3.3686-21, 1.2.3685-21, 2.1.3684-21, en lien hypertexte vers consultant.ru. Pour les niches YMYL, c’est critique : Google et Yandex pénalisent durement les pages sans validation d’autorité.
6 mai : expansion des templates uborka-N-komnatnoj via analyse SERP des concurrents : 1 500 → 1 700-1 900 mots, FAQ 5 → 10. Expansion du template métro : FAQ 3 → 5, ajout d’une section ‘Préparation’, SEO-text. Recrawl de 70 URLs via IndexNow.
7 mai : check croisé GSC + Yandex Webmaster. 39 URLs envoyées en recrawl, correction du flux RSS Yandex Zen (suppression du h1 en double, conversion des tableaux en listes).
Les cinq corrections qui ont vraiment bougé les chiffres
Si je dois choisir les cinq décisions à plus fort impact :
| Décision | Effet |
|---|---|
Un bloc LocalBusiness avec @id dans le footer | Schema plus dupliqué sur 30+ pages, Rich Results Test propre |
| Inter auto-hébergé avec fallback size-adjust:107 % | CLS 0,377 → 0,002 en une journée |
| 100 pages programmatic quartiers/métros à 45 %+ d’unicité | +44 pages dans l’index Yandex en 11 jours (111 → 155) |
| Yandex Webmaster API recrawl + IndexNow + lastmod | Récupération de 92 sur 93 pages depuis Excluded |
| Passages de 134-167 mots avec réponse directe dans les 40-50 premiers | Gain de position sur le cluster ‘nettoyage appartements Saint-Pétersbourg’ : moyenne 28,8 → 16-24 |
Les chiffres
| Métrique | Départ (mars) | 24 avril | 5 mai |
|---|---|---|---|
| Clics GSC / mois | 52 | 97 (+86 %) | en croissance |
| Impressions GSC / mois | 2 826 | 5 359 (+90 %) | jusqu’à 595/jour |
| Position moyenne GSC | 28,8 | 27,3 | 16-24 |
| Yandex Searchable | 111 (13.04) | 155 | 194-201 |
| Yandex Excluded | 56 (13.04) | 92 | 1 |
| CLS | 0,377 | - | 0 |
| LCP mobile | ~4,5 s | - | 2,4 s |
| Lighthouse Performance | ~60-70 | - | 93/100 |
| SEO Health Score | 62 | 72 (10.04) | 84 (23.04) |
Top requêtes Yandex par impressions au 7 mai : ‘services de nettoyage Saint-Pétersbourg prix’ - 103 impressions, ‘nettoyage industriel prix au m²’ - 79, ‘coût nettoyage’ - 77, ‘nettoyage Saint-Pétersbourg’ - 72. Sur les clics : requêtes de marque dans le top-3, plus ‘nettoyage entreprises industrielles’ et ‘nettoyage parkings souterrains’ (27 impressions en position 6, après la réécriture H2 et FAQ).
La suite
Sur ma liste à la fin de la séquence 50 jours :
- Chaîne YouTube + 5 vidéos - corrélation avec les citations IA à 0,737, le signal le plus fort
- Entrée Wikidata pour l’entreprise
- Reddit - 10 à 15 réponses d’expert par mois
- Page LinkedIn entreprise
- 6 annuaires en première vague : Cleannow, Orgpage, Cataloxy, Rosfirm, Spr, Profi.ru
- 1-2 publications dans la presse business de Saint-Pétersbourg → ensuite Wikipedia ru
- llms-en.txt - version anglaise pour les IA globales
Bilan. Un nouveau site peut atteindre un état où Yandex maintient 200 pages dans l’index et où les clics GSC doublent, en 50 jours, sans budget liens. Conditions : tout à la main, pas de thème CMS clé en main pour la niche, contrôle direct sur schema et performance, discipline de cadence blog, recrawl via API.
Si vous avez un site B2B sur une niche locale et qu’il faut accélérer le SEO de manière structurelle, écrivez-moi sur Telegram @dimik90.
À lire aussi : comment je travaille - sans blabla, sans propositions de 40 pages.