# Metaobject definitions — run once against the Admin GraphQL API (2025-01) # via the Shopify MCP graphql_mutation tool, Admin API, or a migration script. # Order matters: create tier_pool first is fine (references are by type name), # but create BOTH before seeding, since cycle references tier_pool and vice-versa. # --------------------------------------------------------------------------- # 1) wineclub_tier_pool # --------------------------------------------------------------------------- mutation CreateTierPoolDefinition { metaobjectDefinitionCreate(definition: { name: "Wine Club Tier Pool" type: "wineclub_tier_pool" access: { storefront: PUBLIC_READ } capabilities: { publishable: { enabled: true } } fieldDefinitions: [ { name: "Cycle", key: "cycle", type: "metaobject_reference" } { name: "Tier", key: "tier", type: "single_line_text_field" } { name: "Tier label", key: "tier_label", type: "single_line_text_field" } { name: "Bottle count", key: "bottle_count", type: "number_integer" } { name: "Base price", key: "base_price", type: "money" } { name: "Default wines", key: "default_wines", type: "list.product_reference" } { name: "Swap pool", key: "swap_pool", type: "list.product_reference" } { name: "Upgrade target", key: "upgrade_target", type: "metaobject_reference" } ] }) { metaobjectDefinition { id type } userErrors { field message code } } } # --------------------------------------------------------------------------- # 2) wineclub_cycle # --------------------------------------------------------------------------- mutation CreateCycleDefinition { metaobjectDefinitionCreate(definition: { name: "Wine Club Cycle" type: "wineclub_cycle" access: { storefront: PUBLIC_READ } capabilities: { publishable: { enabled: true } } fieldDefinitions: [ { name: "Name", key: "name", type: "single_line_text_field" } { name: "Cadence", key: "cadence", type: "single_line_text_field" } { name: "Open at", key: "open_at", type: "date" } { name: "Close at", key: "close_at", type: "date" } { name: "Status", key: "status", type: "single_line_text_field" } { name: "Tier pools", key: "tier_pools", type: "list.metaobject_reference" } ] }) { metaobjectDefinition { id type } userErrors { field message code } } } # --------------------------------------------------------------------------- # 3) Wine product metafield definitions (namespace: wineclub) # So swap-panel grouping, vintage and red/white render from real products. # --------------------------------------------------------------------------- mutation CreateWineMetafieldDefs { vintage: metafieldDefinitionCreate(definition: { name: "Vintage", namespace: "wineclub", key: "vintage", ownerType: PRODUCT, type: "single_line_text_field", access: { storefront: PUBLIC_READ } }) { createdDefinition { id } userErrors { field message } } wineType: metafieldDefinitionCreate(definition: { name: "Wine type", namespace: "wineclub", key: "wine_type", ownerType: PRODUCT, type: "single_line_text_field", access: { storefront: PUBLIC_READ } }) { createdDefinition { id } userErrors { field message } } catalogGroup: metafieldDefinitionCreate(definition: { name: "Catalog group", namespace: "wineclub", key: "catalog_group", ownerType: PRODUCT, type: "single_line_text_field", access: { storefront: PUBLIC_READ } }) { createdDefinition { id } userErrors { field message } } } # --------------------------------------------------------------------------- # 4) Customer selection metafield (written by the App Proxy Worker) # Storefront read so the portal can hydrate a returning customer's saved box. # --------------------------------------------------------------------------- mutation CreateCustomerSelectionDef { metafieldDefinitionCreate(definition: { name: "Wine club selection", namespace: "wineclub", key: "selection", ownerType: CUSTOMER, type: "json", access: { storefront: PUBLIC_READ, admin: MERCHANT_READ_WRITE } }) { createdDefinition { id } userErrors { field message } } }