Ai

Guide technique SEO local prêt-production : pratiques avancées

Implémentez en 60–120 min un SEO local robuste : Nginx sans « if », canonicals, JSON-LD complet, Core Web Vitals, API Google Business (OAuth2 & service…

Damien Larquey

Damien Larquey

February 23, 2026
5 min read
Guide technique SEO local prêt-production : pratiques avancées

Summary

Implémentez en 60–120 min un SEO local robuste : Nginx sans « if », canonicals, JSON-LD complet, Core Web Vitals, API Google Business (OAuth2 & service…




Guide technique <a href="https://codolie.com/blog/pourquoi-le-seo-local-en-2025-depend-de">SEO local</a> prêt-production

Guide technique SEO local prêt-production

En 60–120 minutes, posez une base solide pour capter le « map pack », les requêtes « near me » et la recherche vocale/IA. Niveau intermédiaire/avancé. Focus : précision, performance, sécurité, observabilité.

1) Objectif

Livrer un site prêt-production optimisé pour le SEO local :

  • Cohérence NAP (Name, Address, Phone).
  • Pages de localisation et de services structurées.
  • Balisage JSON-LD LocalBusiness, FAQPage et AggregateRating complet et conforme aux directives Google.
  • Redirections et canonicals fiables (Nginx sans if, <link rel="canonical"> absolus).
  • Core Web Vitals mobile-first, HTTP/2, compression, cache long.
  • Sitemaps partitionnés et indexés.
  • Intégration API Google Business Profile (OAuth2 et service accounts, quotas dynamiques, backoff idempotent).
  • Observabilité : GA4, Search Console, GBP Insights, Lighthouse CI, audit logs.

2) Prérequis

  • Accès au code, serveur/proxy (Nginx compilé HTTP/2, Brotli ou CDN), DNS.
  • Comptes Google Search Console, GA4, identifiants OAuth2 et/ou service account (domain-wide delegation) pour GBP API.
  • Environnements dev/staging/prod, CI/CD, gestion des logs et alertes.
  • Budget estimé : audit 500–2 000 $, pages 50–200 $ l’unité.

3) Implémentation pas à pas

Étape 1 – TLS/HTTP2, redirections & canonicals

Évitez les if et l’en-tête Link dynamique ; préférez une règle de réécriture et des balises <link rel="canonical"> absolues.

Visualizing how local SEO connects a business with nearby customers across maps, search, and reviews.
Visualizing how local SEO connects a business with nearby customers across maps, search, and reviews.
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate     /etc/ssl/certs/example.crt;
    ssl_certificate_key /etc/ssl/private/example.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    root /var/www/html;

    # Réécrire sans 'if' pour forcer le slash final
    rewrite ^([^.]*[^/])$ $1/ permanent;

    location / {
      try_files $uri $uri/ =404;
    }
}

Dans chaque <head> :

<link rel="canonical" href="https://example.com/chemin/page/" />

Étape 2 – Core Web Vitals mobile-first

  • Compression Brotli + gzip fallback :
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript application/json image/svg+xml;
  • Cache-control long (1 an, immutable) pour assets.
  • Images AVIF/WebP, srcset, loading="lazy", fetchpriority.
  • Inline critical CSS, preconnect, defer/async JS.

Étape 3 – JSON-LD LocalBusiness, FAQPage, AggregateRating

Rendu server-side dans le <head> ou début du <body>. Exemple pour une boulangerie :

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Bakery",
  "name": "Boulangerie Dupont",
  "@id": "https://example.com/lyon/cordeliers/",
  "url": "https://example.com/lyon/cordeliers/",
  "image": ["https://example.com/static/storefront.webp"],
  "telephone": "+33 4 72 00 00 00",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "12 Rue des Cordeliers",
    "addressLocality": "Lyon",
    "addressRegion": "Auvergne-Rhône-Alpes",
    "postalCode": "69002",
    "addressCountry": "FR"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 45.7597,
    "longitude": 4.8340
  },
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
      "opens": "07:00",
      "closes": "19:00"
    }
  ],
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": 4.7,
    "reviewCount": 132
  },
  "sameAs": [
    "https://www.facebook.com/boulangeriedupont",
    "https://www.instagram.com/boulangeriedupont"
  ]
}
</script>

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Livrez-vous à domicile ?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Oui, livraison sur Lyon pour toute commande supérieure à 20 €."
      }
    }
  ]
}
</script>

Note : respectez les politiques Google sur les avis (minimum 5 avis pour AggregateRating, données modérées onsite). Évitez les balises dupliquées entre pages.

Diagram of the phased approach to building and scaling a local SEO program.
Diagram of the phased approach to building and scaling a local SEO program.

Étape 4 – Pages localisation & services

  • URL structurées (/ville/quartier/, /services/nom-service/), contenu riche > 300 mots.
  • Inclure intro locale, NAP, horaires, CTA (appel/itinéraire), carte, FAQ, visuels, témoignages.
  • Maillage interne : relier chaque service à ses localisations et vice-versa.

Étape 5 – API Google Business Profile & synchronisation

  • OAuth2 recommandée pour compte individuel (flow standard, accès/refresh tokens).
    Voir : https://developers.google.com/my-business/content/authorization
  • Service accounts : nécessite domain-wide delegation et n’est pas pris en charge pour tous les profils. Stocker tokens et clés privées dans un vault sécurisé, mettre en place rotation régulière.
  • Quotas : récupérer dynamiquement via l’API GET /quota, n’hésitez pas à ajuste le backoff
  • Idempotence : joindre un requestId (UUID v4) à chaque requête et/ou exploiter l’ETag pour des requêtes conditionnelles (If-Match, If-None-Match).
  • Backoff exponentiel avec jitter et plafonnement :
async function patchWithBackoff(payload) {
  const maxAttempts = 6;
  const baseDelay = 1000; // ms
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const requestId = uuidv4();
    const headers = { "X-Request-Id": requestId };
    if (etag) headers["If-Match"] = etag;
    const resp = await sendPatch(payload, headers);
    if (resp.ok) return resp;
    if (![429, 500, 502, 503, 504].includes(resp.status)) {
      throw new Error(`API error ${resp.status}`);
    }
    // Exponential backoff with jitter and cap
    const cap = 30000; 
    const delay = Math.min(cap, baseDelay * 2 ** (attempt - 1));
    const jitter = Math.random() * baseDelay;
    await sleep(delay + jitter);
  }
  throw new Error('Échec après plusieurs tentatives'); 
}

Étape 6 – Sitemaps & robots.txt

Partitionnez si > 50 000 URL, listez les sous-sitemaps dans sitemap-index.xml.

User-agent: *
Disallow: /search
Allow: /

Sitemap: https://example.com/sitemap-index.xml

Étape 7 – Crawl-budget & indexation

  • Identifiez les pages low-value (thin content) : noindex ou fusion.
  • Priorisez pages de conversion et zones stratégiques.
  • Attribuez priority et changefreq dans les sitemaps.

4) Vérification & tests automatisés

  • curl -I https://example.com/lyon/cordeliers/ → statut 200, HTTP/2, SSL ok, balise canonical.
  • Rich Results Test CLI/API pour LocalBusiness et FAQPage.
  • Lint JSON-LD (outil Google ou npm ld lint).
  • Lighthouse CI : perf ≥ 0.80, accès ≥ 0.90, LCP < 2.5 s, CLS < 0.1.
  • Search Console : couverture sans erreurs, sitemaps valides.
  • GA4 : événements et UTMs GBP remontés.
  • GBP : vérifiez la consistance des horaires et consultez les audit logs.

5) Dépannage courant

  • Contenu dupliqué : revérifiez vos canonical, enrichissez ou fusionnez.
  • Horaires site/GBP divergents : cron job de sync + alertes.
  • Rich results absents : assurez-vous du rendu SSR du JSON-LD.
  • Écarts CWV staging/prod : comparer cache, network et RUM.
  • Suspension GBP : ralentissez la cadence, conservez logs et requestId.
  • Problèmes NAP sur mobile : ne modifiez que l’affichage CSS, JSON-LD reste inchangé.

6) Prochaines étapes

Planifiez des revues mensuelles : audits Core Web Vitals, Rich Results, couverture SEO. Automatisez alertes via webhook Search Console, exportez GBP Insights. Formez l’équipe pour maintenir la cohérence NAP et les horaires à jour.

Connecting real-world local searches on mobile with website analytics and business outcomes.
Connecting real-world local searches on mobile with website analytics and business outcomes.

Damien Larquey

Damien Larquey

Building digital products with AI, modern architecture, and product strategy at Codolie.

Back to blog