Skip to content
Français English

Technical guide

Technical SEO: the guide, from crawl to monitoring

By · Last updated: September 10, 2026 · Google Search Central sources checked on 8 September 2026

Technical SEO covers the conditions that let Google crawl, render, index and correctly understand the pages of a site. Until they are met, content and links do not count: they have not been read. This guide goes through the checks we run during our audits, with the fix for each, as we implemented it on this site.

Every section separates two things: what Google documents, with the Search Central page we consulted, and what we recommend, which is our interpretation and our way of implementing it. A SEOForge recommendation is never presented as Google's position.

Not every technical problem carries the same weight

An audit that delivers a hundred flat findings is unusable. We rank every problem on three impact levels, and each section of this guide states the typical level of the problems it covers.

  • Blocking: the page cannot be seen or understood. Examples: a whole template disallowed in robots.txt or marked noindex by mistake; a client-side rendered site whose initial HTML holds neither text nor links.
  • Important: the page is seen, but the signal is blurred or diluted. Examples: redirect chains inherited from two redesigns; non-reciprocal hreflang pairs, or a canonical that contradicts the internal links.
  • Optimisation: the page is correct and could do better. Examples: Article markup without author or dates; an LCP in the orange on mobile.

The order of fixes follows the level, never the count: one blocking issue comes before twenty optimisations.

1. Crawling and crawl budget impact: blocking

Crawling is the first condition. The robots.txt file, the sitemap, status codes and redirects decide what Googlebot requests and what it receives.

What Google documents. Google defines crawl budget as "the set of URLs that Google can and wants to crawl", a combination of a crawl capacity limit, so the server is not overloaded, and a crawl demand tied to the site's size, update frequency and quality. Its page on managing crawl budget targets large sites, over a million pages or over ten thousand pages changing daily, and lists its best practices: consolidate duplicate content, block crawling of unimportant URLs with robots.txt, return 404 or 410 for removed pages, eliminate soft 404s, keep sitemaps up to date with lastmod, avoid long redirect chains, and monitor crawling in Search Console.

What we recommend. A hundred-page site has no budget problem, but it benefits from the same rules, for the clarity of the signal: one redirect per old URL, never a chain; a sitemap generated from the application's routes, never a static file that ages; a robots.txt limited to the areas that are truly useless, admin, API, technical fragments; a real 404 for what no longer exists, not a home page served with a 200.

How to check

On the command line, for every known old URL: curl -sI https://your-site.com/old-url must return a single 301 to the final URL. In Search Console, the "Crawl stats" report, under settings, gives the codes returned to Googlebot, and the "Pages" report lists URLs "with redirect". The most frequent cases, chains, loops, mass 404s after a redesign, are detailed in our article on the ten technical SEO mistakes.

How to fix

The redirect lives at the server or application level, straight to the final URL, keeping the query string, and robots.txt lists only what has no business in the index.

# nginx: straight to the final URL, never to a URL that redirects itself
location = /old-service {
    return 301 https://your-site.com/seo-geo/new-service$is_args$args;
}

# robots.txt: only the areas useless to the index
User-agent: *
Disallow: /admin/
Disallow: /api/
Sitemap: https://your-site.com/sitemap.xml

What we did on seoforge.fr

Every old service URL is redirected with a 301 to its new address by a dedicated controller, query string kept, and an automated test checks that none of those redirects calls another one. The sitemap is an application route: it lists the pages from the site map, and each page's lastmod comes from the git history of its template, an article's from its update field.

2. Indexing and canonicalisation impact: blocking

A crawled page is not necessarily indexed, and an indexed page is not necessarily indexed under the URL you intended. This section covers noindex, canonicals and duplicates.

What Google documents. On consolidating duplicate URLs, Google explains that if you do not specify a canonical URL it "will identify which version of the URL is objectively the best version to show to users", that the rel="canonical" annotation is supported among other signals, that it recommends adding the same self-referential canonical to the canonical page itself, that a permanent redirect is "a strong signal" that the target should become canonical, and that with hreflang the canonical must be a page in the same language.

What we recommend. One URL form per piece of content: no parameters, no trailing slash, no www, with the language prefix, and that same form in the canonical, the sitemap, the internal links and the hreflang. Noindex goes in the robots meta tag for a page, in the X-Robots-Tag HTTP header for a non-HTML response or a fragment loaded in the background. A noindex only works on a page the crawler can read: never combine it with a robots.txt disallow.

How to check

In Search Console, the "Pages" report separates indexed pages from excluded ones, with the reason: "Duplicate, Google chose different canonical than user" is the case to handle first. The "URL Inspection" tool shows the declared canonical and the one Google selected. On the command line: curl -s URL | grep -i canonical and curl -sI URL | grep -i x-robots-tag.

How to fix

An absolute canonical in the head, and a noindex only where it is truly intended.

<!-- in the head of every indexable page -->
<link rel="canonical" href="https://your-site.com/en/guides/technical-seo">

<!-- page to exclude: robots meta -->
<meta name="robots" content="noindex, nofollow">

# non-HTML response or background fragment: HTTP header
X-Robots-Tag: noindex, nofollow

What we did on seoforge.fr

Every page's canonical is built by a single service from the route: query string removed, trailing slash removed, https enforced, www dropped, language prefix always present. The sitemap and the hreflang use exactly the same form. The result fragments of our free tools, loaded in the background, answer with an X-Robots-Tag: noindex header, and a test checks that no sitemap URL carries that header.

3. Architecture and internal linking impact: important

Google discovers and ranks pages through the links they receive. An orphan page, or one buried six clicks from the home page, is crawled late and understood poorly.

What Google documents. Google "uses links as a signal when determining the relevancy of pages and to find new pages to crawl". It "can only crawl your link if it's an <a> HTML element with an href attribute", it "can't reliably extract URLs" from elements that act as links through script events, and it reads the anchor text as information about the linked page (link best practices).

What we recommend. A hierarchy declared once, from which everything derives: every page has a parent, a depth of at most three levels from the home page, a visible breadcrumb and contextual HTML links to its sibling pages. Internal linking cannot be maintained by hand: as soon as the "see also" lists live in the templates, they drift from reality within months. The page-level criteria, titles, anchors, structure, are in our on-page SEO checklist.

How to check

Compare the sitemap's URL list with the pages reached by a crawl from the home page: the difference is your orphan pages. Search Console's "Links" report ranks your pages by internal links received; the bottom of the list is what needs linking. A desktop crawler gives the click depth of every page.

How to fix

The fix is not a link added by hand; it is a single source for the hierarchy, read by the navigation, the breadcrumb and the related-pages blocks.

# site map: one node per page, single source of the menu,
# the breadcrumb, the "see also" blocks and the sitemap order
audit_service:
  parent: seo_geo
  related: [seo_tech_guide, cwv_service, speed_tool]

<!-- rendered: a real link, a real anchor -->
<nav aria-label="Breadcrumb"><ol>
  <li><a href="/en">Home</a></li>
  <li><a href="/en/seo-geo">SEO &amp; GEO</a></li>
  <li aria-current="page">Technical SEO audit</li>
</ol></nav>

What we did on seoforge.fr

The whole hierarchy of the site lives in a topic map: one node per page, with its parent, its hub and its related pages. The menu, the visible breadcrumb and its BreadcrumbList markup, the "see also" blocks and the sitemap order all derive from it. A command rebuilds the internal link graph and fails if a page receives fewer than three content links, or if a hub forgets one of its children.

4. Rendering and JavaScript impact: blocking

What the crawler receives in the HTTP response is read at once. What JavaScript adds afterwards is read later, and not by every bot.

What Google documents. Google processes JavaScript web apps "in three main phases: crawling, rendering, indexing". "Once Google's resources allow, a headless Chromium renders the page and executes the JavaScript"; the page "may stay on this queue for a few seconds, but it can take longer than that". Google adds that "server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript", and that Googlebot "uses HTTP status codes to find out if something went wrong when crawling the page" (JavaScript SEO basics).

What we recommend. Content, title, meta description, canonical and links are in the initial HTML; JavaScript is for interaction, not for content. A fully client-side application goes through server-side rendering or pre-rendering at deploy time. A route that does not exist returns a real 404, never a 200 shell that displays "page not found" after the script runs.

How to check

Compare raw HTML with rendered HTML: curl -s URL | grep -c "<h1" must find the heading without running any script. In Search Console, "URL Inspection" then "Test live URL" shows the screenshot and the HTML as Google rendered it; whatever is missing there is missing for Google.

How to fix

The content goes into the response; the script only adds interaction.

<!-- shell: nothing to read without JavaScript -->
<body><div id="app"></div><script src="/app.js"></script></body>

<!-- server rendered: the content is in the response, the script only adds interaction -->
<body>
  <main><h1>Technical SEO audit</h1><p>What we check…</p></main>
  <script src="/app.js" defer></script>
</body>

What we did on seoforge.fr

Every page is rendered server-side by templates: the HTML received contains the text, the title, the canonical and the links. JavaScript is for interaction: the results of our free tools are loaded afterwards from a fragment marked noindex, and the tool page is complete without it.

5. Performance impact: optimisation

Performance is a pillar of its own: the metrics in our Core Web Vitals guide, the fixes in the web performance guide. Here, only what belongs to the technical audit.

What Google documents. The three Core Web Vitals and their thresholds: an LCP "within the first 2.5 seconds", an INP "of less than 200 milliseconds", a CLS "of less than 0.1". Google states that these signals, "along with other page experience aspects", align "with what our core ranking systems seek to reward", and that the Core Web Vitals report in Search Console shows how your pages perform (Core Web Vitals and search results).

What we recommend. Measure with field data, not only in the lab, and fix in the order LCP, CLS, INP. Server response time conditions LCP: an HTTP cache on anonymous pages is the first lever, before any image optimisation.

How to check

Our speed test gives a page's score and three metrics; Search Console's "Core Web Vitals" report gives the state of the whole site, by group of pages.

How to fix

The two moves that come back in every audit: an HTTP cache on anonymous pages, and declared dimensions on images.

# anonymous page: cacheable, revalidated after five minutes
Cache-Control: public, max-age=300, must-revalidate

<!-- hero image preloaded, dimensions declared: LCP and CLS -->
<link rel="preload" as="image" href="/img/hero.avif">
<img src="/img/hero.avif" width="1200" height="630" alt="…">

What we did on seoforge.fr

Public pages are served by Symfony's application HTTP cache, five minutes with revalidation; the sitemap and the llms.txt file are cached for an hour. When performance is the subject, the Core Web Vitals optimisation service takes over.

6. Structured data impact: optimisation

Structured data tells Google what the page is about and who publishes it. It does not make a page indexable; it makes it understandable.

What Google documents. Structured data is "a standardized format for providing information about a page and classifying the page content". Google "recommends using JSON-LD for structured data if your site's setup allows it", asks that it describe the content of that page, without adding "structured data about information that is not visible to the user", and offers the Rich Results Test to validate it (how structured data works).

What we recommend. One graph per site, Organization and WebSite, to which every page attaches its own nodes by identifier: Service and Offer with a price on a commercial page, Article with a Person author and real dates on a guide, BreadcrumbList derived from the breadcrumb everywhere, FAQPage only on pages that display a FAQ. Mark up only what the page shows.

How to check

Google's Rich Results Test for one page; Search Console's "Enhancements" reports for the whole site. On the command line, curl -s URL | grep -o '<script type="application/ld+json">.*</script>' shows what is really emitted.

How to fix

One JSON-LD block per page, generated by the template from the same data as the visible content.

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {"@type": "ListItem", "position": 1, "name": "Home", "item": "https://your-site.com/en"},
    {"@type": "ListItem", "position": 2, "name": "SEO & GEO", "item": "https://your-site.com/en/seo-geo"},
    {"@type": "ListItem", "position": 3, "name": "Technical SEO audit"}
  ]
}

What we did on seoforge.fr

An Organization, LocalBusiness and WebSite graph is emitted by the base template, and every page attaches its nodes to it by identifier: Service and Offer with a price, Article and Person for the guides, BreadcrumbList computed from the site map. A test walks every page, validates the JSON-LD and checks the list of expected types, including the absence of FAQPage outside the pages that display a FAQ.

7. International and hreflang impact: important

A two-language site has to tell Google which version to show to whom. An incomplete hreflang breaks nothing visible, but it sends the wrong page to the wrong visitors.

What Google documents. "Each language version must list itself as well as all other language versions"; "if two pages don't both point to each other, the tags will be ignored". The reserved x-default value names the page to show for any language not listed. Codes follow ISO 639-1 for the language, with an optional ISO 3166-1 alpha 2 region, URLs must be fully qualified including the protocol, and the three methods, link tags in the head, HTTP headers or the sitemap, are equivalent (localized versions of a page).

What we recommend. One language, one URL prefix. A complete set, fr, en and x-default, on every indexable page, generated by the same code as the canonical. Never an hreflang to a page that does not exist in the other language: better to omit it than to point at a redirect or a 404. The canonical stays in the page's language, and the same alternates are repeated in the sitemap.

How to check

curl -s URL | grep hreflang on the French version, then on the English one: both must list the same URLs. A desktop crawler flags non-reciprocal pairs and alternates that return anything but a 200; this is the check to automate, since a single page migrated without its twin is enough to break the pair.

How to fix

The complete, absolute set, on both pages.

<!-- identical on /fr/guides/seo-technique and /en/guides/technical-seo -->
<link rel="alternate" hreflang="fr" href="https://your-site.com/fr/guides/seo-technique">
<link rel="alternate" hreflang="en" href="https://your-site.com/en/guides/technical-seo">
<link rel="alternate" hreflang="x-default" href="https://your-site.com/fr/guides/seo-technique">

What we did on seoforge.fr

The hreflang tags are generated by the same service as the canonical, from the route: fr, en and x-default to the French page. An automated test reads the sitemap, visits every URL, requires a complete set and checks that every fr/en pair is reciprocal. Articles with a translated title pass their slug per language, and a missing language gets no hreflang rather than a link to a 404.

8. Monitoring impact: important

A technically clean site stays clean as long as it is watched. Three sources complement each other: what Google reports, what the server sees go by, and what the code guarantees before every release.

What Google documents. Search Console "provides information on how Google crawls, indexes, and serves websites". The indexing report gives "an overview of all the pages Google indexed or tried to index in your website", the "Performance" report shows the traffic from Google Search "including breakdowns by queries, pages, and countries", and the "URL Inspection" tool provides a page's index status, a live test and a way to ask Google to crawl it (getting started with Search Console).

What we recommend. A weekly review of three reports, "Pages", "Performance" and "Core Web Vitals", with an alert on any drop in the number of indexed pages. Server logs as a complement: they show what Googlebot actually requests, the codes it receives and the junk URLs it crawls. Finally, automated tests in the site's repository, which fail before the release rather than after it.

How to check

On the access logs, the distribution of the codes returned to Googlebot says in one line whether something broke.

How to fix

The fix is a procedure: every check in this guide becomes a test that blocks the deployment when it fails, and the server log is read every week.

# codes returned to Googlebot this week, by frequency
grep -i googlebot access.log | awk '{print $9}' | sort | uniq -c | sort -rn

# URLs requested by Googlebot that are not in the sitemap
grep -i googlebot access.log | awk '{print $7}' | sort -u > crawled.txt
grep -o '<loc>[^<]*' sitemap.xml | sed 's/<loc>//' | sort -u > sitemap.txt
comm -23 crawled.txt sitemap.txt

What we did on seoforge.fr

The checks in this guide are automated tests in the site's repository, run before every deployment: redirects without chains, complete sitemap with no disallowed URL, reciprocal hreflang, canonical, title and description lengths, expected JSON-LD on every page, no placeholder text. Search Console remains the source for what Google actually did with those pages.

What a technical SEO audit delivers with us

  1. The priority problems identified, ranked blocking, important, optimisation.
  2. The crawl and indexing analysis: robots.txt, sitemap, status codes, redirects, excluded pages and their reason.
  3. The analysis of the architecture, the internal linking and the technical signals: canonical, hreflang, rendering, structured data, performance.
  4. The recommendations ranked by impact, with the estimated effort for each.
  5. The implementation of the fixes in your code, by us.

On quote, depending on the size and technology of your site; first diagnosis free within 24 working hours. The audit does not stop at the report: the fixes are implemented, not only listed.

Where to start

Run the speed test on your most important page: it gives the score, the Core Web Vitals and the first SEO points. To go further, the Technical SEO Audit covers the eight sections of this guide across your whole site, alone or within the Growth Audit, which adds the Ads analysis, the e-mail check and a 90-day action plan. On the AI side, the AI search optimisation guide covers what answer engines expect on top.

Call us Book 20 min