Skip to content
Ende Sun
Back to blog

AI & automation

Reproducible technical SEO with AI: structured data and 301 redirects you can verify

5 min read

Reproducible technical SEO with AI: structured data and 301 redirects you can verify

When I build or migrate a website, two technical SEO tasks come up almost every time: adding structured data so search engines understand the content, and redirecting old URLs to new ones without losing what the old site had earned. Both are tedious to write by hand and easy to get subtly wrong. Both are also good candidates for AI, as long as the output is treated as a draft and checked with independent tools.

Over time I turned each of them into a short, reusable procedure in my notes. The value is not the prompt itself, which is short, but the sequence: generate, validate with a tool, then validate again with a second opinion.

Part 1: structured data with schema.org

Structured data is not the same as rich results

The first distinction I keep written down: structured data and rich results are related but different things.

  • Structured data is markup, usually JSON-LD using the schema.org vocabulary, that describes what a page is about: an organization, a local business, a product, an article.
  • Rich results are the enhanced listings a search engine may show when it finds valid structured data of a supported type.

Valid structured data does not guarantee a rich result. Keeping the two apart avoids testing the wrong thing.

Generating it

The first prompt is deliberately open:

Tell me which schema.org structured data you would add to my website.

I give it the site's URL or the relevant HTML, and the answer is a list of suggested types with a JSON-LD script for each. For a typical small business site the result looks like this (sanitized to a neutral example):

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Example Studio",
  "url": "https://www.example.com/",
  "logo": "https://www.example.com/logo.png",
  "sameAs": [
    "https://www.linkedin.com/company/example-studio",
    "https://www.instagram.com/example.studio"
  ]
}
</script>

That script goes into the page's <head>; on a static site, into index.html.

Then comes a second, equally short prompt that catches what the first one missed:

Tell me which structured data I am still missing for it to be complete.

Asking for gaps, instead of asking for everything at once, tends to surface properties and types the first answer skipped.

Validating it

The script never goes to production just because the model produced it. I validate it twice, with two different tools that answer two different questions:

  1. The schema.org validator (validator.schema.org): is the markup syntactically valid and correctly typed?
  2. Google's Rich Results Test (search.google.com/test/rich-results): does this page qualify for any rich result?

If the first passes and the second does not, the markup is fine but the type is not one that produces an enhanced listing, which is exactly the structured data versus rich results distinction from above. I also check every value against reality: a model will happily fill in a plausible phone number or logo path that does not exist.

Part 2: 301 redirects without loops

The problem

During a migration, every old URL that already has traffic or links needs a permanent redirect to its new equivalent. On Apache hosting that usually means RewriteRule lines in .htaccess. Writing dozens of them by hand is error-prone, and the typical mistakes are subtle: redirect loops, double slashes, or rules that chain into several hops.

The prompt as a specification

Here the prompt is less a question and more a specification. These are the requirements I always include:

  • 1:1 mapping between each source URL and its destination.
  • 301 permanent redirects.
  • No loops and no double slashes (//).
  • A global rule that redirects any URL requested without a trailing slash to the version with one, except when the last segment looks like a file (it contains a dot).
  • Output as one complete block ready to paste inside <IfModule mod_rewrite.c>.

After the requirements comes the mapping itself, one line per URL:

https://oldsite.example.com/en/tickets -> https://newsite.example.com/en/tickets/
https://oldsite.example.com/es/entradas -> https://newsite.example.com/es/entradas/
https://oldsite.example.com/fr/billets -> https://newsite.example.com/fr/billets/

Writing the requirements explicitly matters more than the wording. A model asked to "create some redirects" will produce something that looks right; a model given the loop and slash constraints will usually write patterns that respect them.

A sanitized example of the kind of block I expect back:

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Specific 1:1 mappings. The optional slash (/?) accepts both variants
    RewriteRule ^en/tickets/?$ https://newsite.example.com/en/tickets/ [R=301,L]
    RewriteRule ^es/entradas/?$ https://newsite.example.com/es/entradas/ [R=301,L]
    RewriteRule ^fr/billets/?$ https://newsite.example.com/fr/billets/ [R=301,L]

    # Global rule: add a trailing slash to paths that do not look like files
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !\.[A-Za-z0-9]+$
    RewriteCond %{REQUEST_URI} !/$
    RewriteRule ^(.*)$ /$1/ [R=301,L]
</IfModule>

Reviewing the order

One thing I always review by hand is the order of the rules. Apache processes rules from top to bottom, and [L] stops at the first match. If the global trailing-slash rule runs first on the old domain, a request for /en/tickets is first redirected to /en/tickets/ on the same domain, and only then to the new site: two hops where one would do. Putting the specific mappings first, with patterns that accept the URL with or without the slash, avoids that chain. Whatever order the model chooses, I make sure it is a deliberate one.

Validating it

As with structured data, nothing gets deployed on the model's word:

  1. An .htaccess tester (technicalseo.com/tools/htaccess/): I paste the rules and test real source URLs to see exactly where each one ends up.
  2. A second AI as a reviewer, with a narrow question:
Analyze this .htaccess and tell me whether it would cause a critical error.

A reviewer that did not write the rules looks at them differently, and asking specifically for critical errors keeps the answer focused on loops, broken syntax and unreachable rules instead of style.

Only after both checks do the rules go to the server, and I still request a few of the old URLs in a browser right after deploying.

Why I keep these as procedures

Neither procedure is sophisticated. The point is that they are written down and repeatable: the same prompts, the same requirements, the same two independent validation steps, every time. AI makes producing the first draft fast. The written procedure and the validation tools are what make the result trustworthy.