Purpose
If your robots.txt doesn't address the AI crawlers by name — or worse, disallows them — assistants like ChatGPT, Claude, and Perplexity may never read your store, so you simply don't exist to AI shoppers. Shopify generates robots.txt from a theme template (templates/robots.txt.liquid); this skill reads that template and appends explicit allow rules for the major AI user-agents (with a clear, idempotent managed block) so foundational models and AI search are permitted to crawl your pages. Fixes the agentiq.report finding robots-ai-rules.
Prerequisites
- Authenticated Shopify CLI session (
shopify auth login --store <domain>) - Required API scopes:
read_themes,write_themes
Parameters
All skills accept these universal parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| format | string | no | human | Output format: human (default) or json |
| dry_run | bool | no | true | Preview the new robots.txt.liquid without writing (defaults ON — this edits the live theme) |
Skill-specific parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| theme_id | string | no | — | Theme GID to edit (defaults to the published MAIN theme) |
| agents | string | no | GPTBot,OAI-SearchBot,ChatGPT-User,ClaudeBot,Claude-Web,PerplexityBot,Perplexity-User,Google-Extended,Amazonbot,Applebot-Extended | Comma list of AI user-agents to allow |
| mode | string | no | allow | allow (add Allow rules) or audit (report current state only, no write) |
Safety
⚠️ Step 2 (
themeFilesUpsert) modifies a file in the LIVE published theme. A malformedrobots.txt.liquidcan de-index the store from ALL search engines. This skill writes only inside a clearly-delimited# BEGIN agentic-crawler-access … # ENDmanaged block (re-running replaces just that block, never your other rules), defaultsdry_run: true, and recommends duplicating the theme first. Review the full proposed file before settingdry_run: false.
Workflow Steps
-
OPERATION:
themes— query Inputs:roles: [MAIN](unlesstheme_idgiven), thentheme.files(filenames: ["templates/robots.txt.liquid"])Expected output: Currentrobots.txt.liquidcontent (or absence — Shopify uses a default if the template doesn't exist). -
COMPUTE (no API): construct the new template. If no custom template exists, start from the Shopify default (
{{ robots.default_groups }}) and append the managed block withUser-agent:/Allow: /stanzas for each agent inagents. If a managed block already exists, replace only it. Emit the full proposed file diff. -
OPERATION:
themeFilesUpsert— mutation Inputs:themeId,files: [{ filename: "templates/robots.txt.liquid", body: { type: TEXT, value: <new content> } }](skipped whendry_runormode: audit). Expected output: Upserted theme file; collectuserErrors.
GraphQL Operations
graphql# themes:query — validated against api_version 2025-01 query CrawlerThemeFile { themes(first: 1, roles: [MAIN]) { nodes { id name files(filenames: ["templates/robots.txt.liquid"]) { nodes { filename body { ... on OnlineStoreThemeFileBodyText { content } } } } } } }
graphql# themeFilesUpsert:mutation — validated against api_version 2025-01 mutation CrawlerAllowUpsert($themeId: ID!, $files: [OnlineStoreThemeFilesUpsertFileInput!]!) { themeFilesUpsert(themeId: $themeId, files: $files) { upsertedThemeFiles { filename } userErrors { filename code message } } }
Managed block written into templates/robots.txt.liquid (after {{ robots.default_groups }}):
liquid# BEGIN agentic-crawler-access (managed by shopify-admin-agentic-crawler-access) User-agent: GPTBot Allow: / User-agent: ClaudeBot Allow: / User-agent: PerplexityBot Allow: / User-agent: Google-Extended Allow: / # ... one stanza per agent in `agents` # END agentic-crawler-access
Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗ ║ SKILL: <skill name> ║ ║ Store: <store domain> ║ ║ Started: <YYYY-MM-DD HH:MM UTC> ║ ╚══════════════════════════════════════════════╝
After each step, emit:
[N/TOTAL] <QUERY|MUTATION> <OperationName> → Params: <brief summary of key inputs> → Result: <count or outcome>
If dry_run: true, prefix every mutation step with [DRY RUN] and do not execute it.
On completion, emit:
For format: human (default):
══════════════════════════════════════════════ OUTCOME SUMMARY <Metric label>: <value> Errors: 0 Output: <filename or "none"> ══════════════════════════════════════════════
For format: json, emit:
json{ "skill": "<skill-slug>", "store": "<domain>", "started_at": "<ISO8601>", "completed_at": "<ISO8601>", "dry_run": false, "steps": [ { "step": 1, "operation": "<OperationName>", "type": "query", "params_summary": "<string>", "result_summary": "<string>", "skipped": false } ], "outcome": { "metric_key": 0, "errors": 0, "output_file": null } }
Output Format
human: the before/after robots.txt.liquid and the list of agents now allowed. json: { theme_id, agents_allowed:[...], wrote: true|false, errors }.
Error Handling
| Error | Cause | Recovery |
|---|---|---|
THROTTLED | API rate limit | Wait 2s, retry up to 3 times |
ACCESS_DENIED | Missing write_themes | Abort with a clear scope message; do not partially write |
userErrors on upsert | Invalid template body | Do not write; surface the Liquid error for review |
Best Practices
- Duplicate the published theme before writing (Online Store → Themes → Duplicate) so you can roll back instantly.
- Keep
dry_run: trueuntil you've read the entire proposed file — a brokenrobots.txt.liquidcan de-index the whole store. - Use the managed-block markers; never hand-merge — re-running the skill then cleanly updates only its own block.
- Allowing AI crawlers ≠ giving away content; it's permission to read public pages the same way Googlebot does. Pair with
shopify-admin-agentic-llms-txtso crawlers also get a guided summary.


