Metafield Definition Audit
Read-only: enumerates every metafield definition across all owner types and flags unused, undocumented, or duplicate-key definitions.
shopify-admin-metafield-definition-audit
Purpose
Inventories every metafield definition (PRODUCT, VARIANT, CUSTOMER, ORDER, COLLECTION, COMPANY, LOCATION, and others) and flags definitions that are unused (zero values stored), undocumented (missing description), or share a namespace.key collision across owner types. Definition sprawl is a leading source of theme/app bugs and slow Admin search. Read-only — no mutations. Provides the data foundation for a definition-cleanup workflow.
Prerequisites
shopify store auth --store --scopes read_products,read_customers,read_orders,read_inventory read_products, read_customers, read_orders)Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| owner_types | string | no | all | Comma-separated owner types to scan (e.g. PRODUCT,CUSTOMER); all scans every supported type |
| flag_unused | bool | no | true | Flag definitions whose metafieldsCount is zero |
| flag_undocumented | bool | no | true | Flag definitions with empty/null description |
| flag_duplicates | bool | no | true | Flag namespace.key pairs that exist on more than one owner type |
| format | string | no | human | Output format: human or json |
Safety
> ℹ️ Read-only skill — no mutations are executed. Safe to run at any time. No metafield definitions are deleted, updated, or pinned by this skill.
Workflow Steps
owner_types (default: full list).metafieldDefinitions — query Inputs: For each owner type: first: 250, ownerType: , select id, namespace, key, name, description, type { name }, pinnedPosition, metafieldsCount, validations { name value }, pagination cursor
Expected output: All definitions per owner type with usage counts; paginate until hasNextPage: false
unused — metafieldsCount == 0 and flag_unused: trueundocumented — description is null or empty and flag_undocumented: trueduplicate_key — namespace.key appears on more than one owner type and flag_duplicates: trueGraphQL Operations
# metafieldDefinitions:query — validated against api_version 2025-01
query MetafieldDefinitionAudit($ownerType: MetafieldOwnerType!, $after: String) {
metafieldDefinitions(first: 250, after: $after, ownerType: $ownerType) {
edges {
node {
id
namespace
key
name
description
ownerType
pinnedPosition
metafieldsCount
type {
name
category
}
validations {
name
value
type
}
access {
admin
storefront
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: Metafield Definition Audit ║
║ 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>
On completion, emit:
For format: human (default):
══════════════════════════════════════════════
METAFIELD DEFINITION AUDIT
Owner types scanned: <n>
Total definitions: <n>
By owner type:
PRODUCT: <n> (unused: <n>, undocumented: <n>)
VARIANT: <n> (unused: <n>, undocumented: <n>)
CUSTOMER: <n> (unused: <n>, undocumented: <n>)
ORDER: <n> (unused: <n>, undocumented: <n>)
Flags:
Unused definitions: <n>
Undocumented definitions: <n>
Duplicate keys: <n>
Examples:
PRODUCT custom.swatch_hex unused (0 values)
CUSTOMER custom.vip_tier undocumented
ORDER+CUSTOMER custom.notes duplicate key across owner types
Output: metafield_def_audit_<date>.csv
══════════════════════════════════════════════
For format: json, emit:
{
"skill": "metafield-definition-audit",
"store": "<domain>",
"owner_types_scanned": 0,
"total_definitions": 0,
"unused_definitions": 0,
"undocumented_definitions": 0,
"duplicate_keys": 0,
"output_file": "metafield_def_audit_<date>.csv"
}
Output Format
CSV file metafield_def_audit_ with columns:
definition_id, owner_type, namespace, key, name, type, description_present, metafields_count, pinned, is_unused, is_undocumented, is_duplicate_key, flags
Error Handling
| Error | Cause | Recovery |
|---|---|---|
THROTTLED | API rate limit exceeded | Wait 2 seconds, retry up to 3 times |
ACCESS_DENIED for an owner type | Caller lacks the read scope for that resource | Skip that owner type with a warning row in the CSV |
metafieldsCount returns null | Owner type does not expose count, or count is still computing | Treat as unknown; do not flag as unused |
| Owner type not supported in API version | Newer owner type not yet available | Skip with warning; re-run after API version upgrade |
Best Practices
namespace.key. Theme liquid may read a definition that has zero saved values yet (e.g., a newly added field that has not been populated).pinnedPosition set) to surface them in the merchant Admin UI; un-pinned but heavily used definitions are a UX smell.custom.notes on both ORDER and CUSTOMER may be intentional) but they almost always indicate copy-paste creation — review for consistency in type and validations.