This is the hand-off page for the eight checks in the AI-Readiness Scorecard and in The State of AI Readiness on the TSX-V. It is written for whoever maintains the website. Each check gets the same three things: what it is, the change to make, and the command that proves it is done.
Every check is a public HTTP request. That is deliberate. It means you can verify each one yourself. It also means "done" is a fact anyone can re-run, not an assurance from us.
Work them in the order below. The order matters. A site has to be reachable before it is worth making findable. It has to be findable before it can be identified as a specific company. And it has to be identified before anything it says is worth quoting. A summary file pointing at pages nobody ever enumerated helps no one.
Replace example.com with your own domain in every command.
1. AI crawlers allowed — reachable
What it is. Whether the AI services are permitted to read the site at all. Nothing else on this list matters if the answer is no.
The change. In /robots.txt, make sure the AI user-agents are not disallowed. But robots.txt is rarely the real problem. The common failure is a security or CDN layer blocking these agents upstream, in a bot-management rule nobody remembers enabling.
User-agent: GPTBot
Allow: /
User-agent: OAI-SearchBot
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: PerplexityBot
Allow: /
Sitemap: https://example.com/sitemap.xml
Prove it.
curl -s https://example.com/robots.txt
Then check the layer in front of the origin. In Cloudflare, look at Security → Bots and any WAF rule matching user-agent; verified-bot rules routinely catch these crawlers. Confirm with the agent's own name:
curl -sI -A "GPTBot" https://example.com/ | head -1
A 200 is a pass. A 403 means something upstream is blocking, regardless of what robots.txt says.
2. XML sitemap present — findable
What it is. A machine-readable list of your pages, so none of them depends on being found by chance.
The change. Publish /sitemap.xml and reference it from robots.txt. Every mainstream CMS does this with a setting or a plug-in. WordPress ships one at /wp-sitemap.xml. Yoast and Rank Math both generate /sitemap_index.xml.
Prove it.
curl -sI https://example.com/sitemap.xml | head -1
curl -s https://example.com/robots.txt | grep -i sitemap
3. Organization schema — identifiable
What it is. The machine-readable record of who the company is. An AI system reads this instead of your homepage. Across the TSX-V it is the single biggest gap: 70% of companies do not have it.
The change. Add a JSON-LD block to the homepage <head>.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Example Metals Corp.",
"legalName": "Example Metals Corporation",
"url": "https://example.com/",
"logo": "https://example.com/logo.png",
"description": "Mineral exploration company advancing copper-gold projects in British Columbia.",
"tickerSymbol": "EXM",
"address": {
"@type": "PostalAddress",
"addressLocality": "Vancouver",
"addressRegion": "BC",
"addressCountry": "CA"
}
}
</script>
Prove it.
curl -s https://example.com/ | grep -o 'application/ld+json'
Then paste the URL into Google's Rich Results Test to confirm the block parses and the type is recognised.
4. Profile links (sameAs) — identifiable
What it is. The links that let an AI system confirm the company it is reading about is the company it was asked about. Without them, a name is just a string.
The change. Add sameAs inside the Organization block from check 3 — it belongs in that record, not in a separate one. Use the profiles that actually exist and resolve.
"sameAs": [
"https://money.tmx.com/en/quote/EXM",
"https://www.sedarplus.ca/csa-party/records/document.html?id=example",
"https://www.linkedin.com/company/example-metals",
"https://en.wikipedia.org/wiki/Example_Metals"
]
Prove it. Every URL must return 200 — a dead sameAs is worse than none, because it asserts an identity that cannot be confirmed.
for u in $(curl -s https://example.com/ | grep -oE 'https://[^"]+' | sort -u); do
printf "%-70s %s\n" "$u" "$(curl -s -o /dev/null -w '%{http_code}' "$u")"
done
5. llms.txt — quotable
What it is. A plain-text file that tells an AI assistant what the company is and which pages matter. 8% of the TSX-V publishes one.
The change. Create /llms.txt. One factual paragraph, then the pages that matter. No marketing language — this file is read, not skimmed.
# Example Metals Corp.
> Mineral exploration company (TSX-V: EXM) advancing the Example copper-gold
> project in British Columbia, Canada. Incorporated 2011, headquartered in
> Vancouver.
## Projects
- [Example Project](https://example.com/projects/example): 12,400 ha, copper-gold porphyry, 2026 drill programme
- [North Zone](https://example.com/projects/north-zone): early-stage, 2025 geophysics
## Investors
- [News releases](https://example.com/news)
- [Financial reports](https://example.com/investors/financials)
- [Share structure](https://example.com/investors/share-structure)
## Contact
- [Investor relations](https://example.com/contact): ir@example.com
Prove it.
curl -s https://example.com/llms.txt | head -20
It must return 200 with plain text, not an HTML 404 page. That is the usual failure, and it is why the check tests the content type and not just the status.
6. Answer / FAQ schema — quotable
What it is. The questions investors actually ask, answered in a format an AI system can lift directly. Two companies out of 805 on the TSX-V have this. It is the cheapest differentiator on the list.
The change. Take the real questions. Where the projects are, what the last results showed, what the share structure is. Publish them as FAQPage JSON-LD on the page that answers them. The answers must also be visible on the page. Markup that contradicts the visible content is a violation, not a shortcut.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Where is Example Metals' flagship project located?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The Example project covers 12,400 hectares in the Golden Triangle of northwestern British Columbia, 60 km north of Stewart, road-accessible from Highway 37."
}
},
{
"@type": "Question",
"name": "What did Example Metals' most recent drill programme return?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The 2026 programme returned 12.4 g/t gold over 6.0 metres from hole EX-26-14 at the North zone, announced 14 May 2026."
}
}
]
}
</script>
Prove it. Rich Results Test again, and:
curl -s https://example.com/investors/faq | grep -o 'FAQPage'
7. Canonical tags — hygiene
What it is. Each page naming its own preferred address, so duplicate URLs do not compete with each other.
The change. One self-referencing canonical per page, absolute, in the <head>.
<link rel="canonical" href="https://example.com/projects/example" />
Prove it.
curl -s https://example.com/ | grep -i 'rel="canonical"'
8. HSTS — hygiene
What it is. A header telling browsers to reach the site only over HTTPS. A standard setting that browsers and crawlers expect; 68% of the TSX-V does not send it.
The change. One header. Start with a short max-age, confirm nothing breaks, then raise it — a long max-age on a misconfigured site is hard to undo.
Strict-Transport-Security: max-age=31536000; includeSubDomains
In Cloudflare it is SSL/TLS → Edge Certificates → HTTP Strict Transport Security. In nginx, add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;.
Prove it.
curl -sI https://example.com/ | grep -i strict-transport-security
Checking all eight at once
This runs every check above and prints a pass/fail line for each. It is the same logic the benchmark uses, in a form you can paste into a terminal.
#!/usr/bin/env bash
D="example.com" # your domain, no scheme
ok() { printf " \033[32m✓\033[0m %s\n" "$1"; }
no() { printf " \033[31m✗\033[0m %s\n" "$1"; }
echo "AI-readiness checks for $D"
curl -sI -A "GPTBot" "https://$D/" | head -1 | grep -q "200" && ok "AI crawlers allowed" || no "AI crawlers allowed"
curl -sI "https://$D/sitemap.xml" | head -1 | grep -qE "200|30[12]" && ok "XML sitemap" || no "XML sitemap"
curl -s "https://$D/" | grep -q 'application/ld+json' && ok "Structured data present" || no "Structured data present"
curl -s "https://$D/" | grep -q '"sameAs"' && ok "Profile links (sameAs)" || no "Profile links (sameAs)"
curl -s "https://$D/llms.txt" | head -1 | grep -qv "<!DOCTYPE" && curl -sI "https://$D/llms.txt" | head -1 | grep -q "200" && ok "llms.txt" || no "llms.txt"
curl -s "https://$D/" | grep -q 'FAQPage' && ok "FAQ schema (homepage)" || no "FAQ schema (homepage)"
curl -s "https://$D/" | grep -qi 'rel="canonical"' && ok "Canonical tag" || no "Canonical tag"
curl -sI "https://$D/" | grep -qi 'strict-transport-security' && ok "HSTS" || no "HSTS"
Two notes on reading the output. The FAQ and canonical checks look at the homepage only, which is how the benchmark scores them. Markup on a sub-page is real and useful, but it will not move the score. And a missing /robots.txt counts as a pass for check 1, because nothing is being blocked. It will still fail check 2, since there is no Sitemap: line for a crawler to follow.
What this does not cover
These eight checks are technical readiness — whether AI systems can read your site. That is the precondition for being cited, not a measure of it. A site that passes all eight and says nothing worth quoting will still not be quoted. What you publish, and whether it answers what people actually ask, is the layer above this one.