How to Automate Structured Data Validation
Set up AI agents and CI/CD pipelines to catch schema.org errors before they reach production.
The problem: structured data breaks silently
Structured data breaks without errors. Google's Rich Results Test checks one page at a time and requires a public URL. During development, you push to staging and deploy to production without validating markup. By the time you notice, rich results have disappeared and the error has been live for days.
Common failure modes:
- A developer changes a date format from ISO 8601 to a human-readable string
- A CMS update breaks the currency code from "USD" to "dollars"
- A new product template omits required fields Google needs for rich results
- A schema enum value has wrong casing ("instock" instead of "InStock")
- An array of sameAs URLs includes a relative path instead of an absolute URL
None of these break the page. None throw a build error. All of them silently degrade your search presence.
The solution: validate at every stage
Three checkpoints where validation should happen:
- During development: your AI agent validates as you code
- In CI/CD: automated check on every pull request
- In production: periodic check of live pages
The XooCode Structured Data Validation API powers all three. Two endpoints (validate a URL, validate raw markup), a structured response with per-block findings, and a markdown prompt your AI agent can use directly. Free tier includes 50 requests per month.
Get your API key
- Sign up at xoocode.com/signup and verify your email
- Go to Account > API Keys
- Click "Create API key", give it a name, and copy the key
- Store it securely (it is shown once)
Test it with curl:
curl -s -X POST https://xoocode.com/api/v1/validate/url/ \
-H "Content-Type: application/json" \
-H "X-Api-Key: xoo_your_key_here" \
-d '{"url": "https://example.com"}' | jq .summaryOption A: Claude Code skill
Install a skill file and Claude Code gets a /structured-data-testing-tool command.
curl -o ~/.claude/skills/structured-data-testing-tool/skill.md \
--create-dirs \
https://xoocode.com/skills/structured-data-testing-tool.mdUsage:
/structured-data-testing-tool https://yoursite.com/product-pageThe skill fetches the page, validates all JSON-LD blocks, and reports findings with fix suggestions. If you are in the codebase that generates the markup, the skill offers to locate the source files and apply fixes directly.
The skill handles API key setup on first use. It checks for a XOOCODE_API_KEY environment variable or a key file at ~/.xoocode/api-key, and walks you through creating one if neither exists.
Full details: Structured Data Testing Tool for Claude Code
Option B: MCP server
For Cursor, Windsurf, or any MCP-compatible editor.
{
"mcpServers": {
"xoocode-structured-data": {
"command": "npx",
"args": ["xoocode-structured-data-mcp"],
"env": {
"XOOCODE_API_KEY": "xoo_your_key_here"
}
}
}
}The server exposes two tools: validate_url and validate_raw. Your agent discovers them via the MCP protocol and can call them without any manual wiring.
Full details: Structured Data MCP Server
Option C: CI/CD pipeline
A GitHub Actions workflow that validates structured data on every pull request.
name: Validate Structured Data
on: [pull_request]
jobs:
validate-schema:
runs-on: ubuntu-latest
steps:
- name: Validate structured data
run: |
RESPONSE=$(curl -s -X POST https://xoocode.com/api/v1/validate/url/ \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${{ secrets.XOOCODE_API_KEY }}" \
-d '{"url": "https://staging.yoursite.com"}')
ERRORS=$(echo "$RESPONSE" | jq '.summary.errors')
if [ "$ERRORS" -gt 0 ]; then
echo "::error::Structured data validation found $ERRORS errors"
echo "$RESPONSE" | jq '.blocks[] | select(.errors | length > 0)'
exit 1
fi
echo "Structured data validation passed"This workflow:
- Runs on every pull request
- Validates the staging URL against schema.org and Google requirements
- Fails the check if any errors are found
- Shows the specific errors in the PR check output
Add your API key as a repository secret: Settings > Secrets > Actions > XOOCODE_API_KEY.
For multiple pages, loop over a list of URLs or use a sitemap parser to check every page.
Option D: Production monitoring
Schedule a weekly check of your live pages.
name: Weekly Schema Check
on:
schedule:
- cron: '0 8 * * 1'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Check production pages
run: |
URLS=(
"https://yoursite.com/"
"https://yoursite.com/products/widget"
"https://yoursite.com/about"
)
FAILED=0
for URL in "${URLS[@]}"; do
RESPONSE=$(curl -s -X POST https://xoocode.com/api/v1/validate/url/ \
-H "Content-Type: application/json" \
-H "X-Api-Key: ${{ secrets.XOOCODE_API_KEY }}" \
-d "{\"url\": \"$URL\"}")
ERRORS=$(echo "$RESPONSE" | jq '.summary.errors')
if [ "$ERRORS" -gt 0 ]; then
echo "FAIL: $URL ($ERRORS errors)"
FAILED=$((FAILED + 1))
else
echo "PASS: $URL"
fi
done
if [ "$FAILED" -gt 0 ]; then
echo "::error::$FAILED pages have structured data errors"
exit 1
fiRuns every Monday at 8am UTC. Add a Slack notification step after the check to alert your team when errors are found.
Pricing and limits
Two tiers:
- Free: 50 requests per month. Enough for a single-site CI check that runs on PRs.
- Pro ($19.99/month): 500 requests per day. For multi-site monitoring, heavy development, and teams.
Manage your plan at Account > Billing.
Next steps
- Try the web tool for quick manual checks
- Read the API docs for the full endpoint reference
- Install the Claude Code skill for in-editor validation
- Set up the MCP server for Cursor and other MCP clients
- Browse JSON-LD examples for reference markup to test against