Cultiva Café — Shopify Custom Data

Metafields & Metaobjects · App de Datos de Origen · CULTIVA IA

shopify-custom-data v1.8
📦

Product Metafields

namespace: $app
process single_line_text_field
altitude_masl number_integer
tasting_notes list.single_line_text_field
score_sca number_decimal
harvest_date date
producer_ref metaobject_reference REF
🌿

Metaobject: Producer

type: $app:producer
name single_line_text_field REQ
country single_line_text_field
region single_line_text_field
bio multi_line_text_field
certifications list.single_line_text_field
shopify.app.toml toml
# ── Cultiva Café: Shopify App Config ──────────────────────────────────────
name = "cultiva-cafe-origin"
client_id = "9a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d"
application_url = "https://cultiva-cafe.myshopify.com"

# ── METAFIELD DEFINITIONS ─────────────────────────────────────────────────

[product.metafields.app.process]
type = "single_line_text_field"
name = "Proceso de Beneficio"
access.admin = "merchant_read_write"
access.storefront = "public_read"

[product.metafields.app.altitude_masl]
type = "number_integer"
name = "Altitud (msnm)"
access.admin = "merchant_read_write"
access.storefront = "public_read"

[product.metafields.app.tasting_notes]
type = "list.single_line_text_field"
name = "Notas de Cata"
access.admin = "merchant_read_write"
access.storefront = "public_read"

[product.metafields.app.score_sca]
type = "number_decimal"
name = "Puntuación SCA"
access.admin = "merchant_read_write"
access.storefront = "public_read"

[product.metafields.app.harvest_date]
type = "date"
name = "Fecha de Cosecha"
access.admin = "merchant_read_write"
access.storefront = "public_read"

[product.metafields.app.producer_ref]
type = "metaobject_reference<$app:producer>"
name = "Productor / Finca"
access.admin = "merchant_read_write"
access.storefront = "public_read"

# ── METAOBJECT DEFINITION: PRODUCER ───────────────────────────────────────

[metaobjects.app.producer]
name = "Producer"
display_name_field = "name"
access.storefront = "public_read"

[metaobjects.app.producer.fields.name]
name = "Nombre del Productor"
type = "single_line_text_field"
required = true

[metaobjects.app.producer.fields.country]
name = "País"
type = "single_line_text_field"

[metaobjects.app.producer.fields.region]
name = "Región"
type = "single_line_text_field"

[metaobjects.app.producer.fields.bio]
name = "Biografía"
type = "multi_line_text_field"

[metaobjects.app.producer.fields.certifications]
name = "Certificaciones"
type = "list.single_line_text_field"
💡 Con shopify app deploy estas definiciones se instalan automáticamente en la tienda. No se usan metafieldDefinitionCreate ni metaobjectDefinitionCreate por GraphQL — eso sería incorrecto para este caso.
upsertProducer.graphql graphql
# Crear/actualizar finca La Esmeralda
mutation {
  metaobjectUpsert(handle: {
    type: "$app:producer",
    handle: "la-esmeralda-panama",
  }, metaobject: {
    fields: [
      {
        key: "name",
        value: "Finca La Esmeralda"
      },
      {
        key: "country",
        value: "Panamá"
      },
      {
        key: "region",
        value: "Chiriquí, Boquete"
      },
      {
        key: "bio",
        value: "Finca familiar con 120 años
de historia cultivando Gesha
a más de 1.700 msnm."
      },
      {
        key: "certifications",
        value: "[\"Rainforest Alliance\",
\"Organic\",\"Cup of Excellence\"]"
      }
    ]
  }) {
    metaobject { id handle }
    userErrors { field message }
  }
}
setProductMetafields.graphql graphql
# Asignar datos al producto Gesha Washed
mutation {
  metafieldsSet(metafields: [
    {
      ownerId: "gid://shopify/Product/8847261",
      key: "process",
      value: "Washed"
    },
    {
      ownerId: "gid://shopify/Product/8847261",
      key: "altitude_masl",
      value: "1750"
    },
    {
      ownerId: "gid://shopify/Product/8847261",
      key: "tasting_notes",
      value: "[\"Jazmín\",\"Melocotón\",
\"Bergamota\",\"Té blanco\"]"
    },
    {
      ownerId: "gid://shopify/Product/8847261",
      key: "score_sca",
      value: "93.5"
    },
    {
      ownerId: "gid://shopify/Product/8847261",
      key: "harvest_date",
      value: "2025-01-15"
    },
    {
      ownerId: "gid://shopify/Product/8847261",
      key: "producer_ref",
      value: "gid://shopify/Metaobject/9912345"
    }
  ]) {
    metafields { key value }
    userErrors { field message }
  }
}
getProductOrigin.admin.graphql admin api
query GetCoffeeOrigin {
  product(id: "gid://shopify/Product/8847261") {
    title
    # Metafields — namespace omitido → $app por defecto
    process: metafield(key: "process") {
      jsonValue
    }
    altitude: metafield(key: "altitude_masl") {
      jsonValue
    }
    notes: metafield(key: "tasting_notes") {
      jsonValue
    }
    score: metafield(key: "score_sca") {
      jsonValue
    }
    producerRef: metafield(key: "producer_ref") {
      reference {
        ... on Metaobject {
          handle
          name: field(key: "name") { jsonValue }
          country: field(key: "country") { jsonValue }
          region: field(key: "region") { jsonValue }
          certs: field(key: "certifications") {
            jsonValue
          }
        }
      }
    }
  }
}
getProductOrigin.storefront.graphql storefront api
query GetCoffeeOriginStorefront {
  product(handle: "gesha-washed-panama") {
    title
    # En Storefront, namespace explícito: "$app"
    process: metafield(
      namespace: "$app"
      key: "process"
    ) { value }

    altitude: metafield(
      namespace: "$app"
      key: "altitude_masl"
    ) { value }

    notes: metafield(
      namespace: "$app"
      key: "tasting_notes"
    ) { value }

    score: metafield(
      namespace: "$app"
      key: "score_sca"
    ) { value }

    producer: metafield(
      namespace: "$app"
      key: "producer_ref"
    ) {
      reference {
        ... on Metaobject {
          handle
          name: field(key: "name") { value }
          certs: field(key: "certifications") {
            value
          }
        }
      }
    }
  }
}

Preview — Product Page: Gesha Washed Panamá

Gesha Washed — Finca La Esmeralda
handle: gesha-washed-panama · gid://shopify/Product/8847261
proceso: Washed
altitud: 1.750 msnm
SCA: 93.5 / 100
cosecha: Enero 2025
Notas de cata:
🌸 Jazmín 🍑 Melocotón 🍊 Bergamota 🍵 Té blanco
Metaobject vinculado — $app:producer
🌿
Finca La Esmeralda
📍 Chiriquí, Boquete · Panamá
handle: la-esmeralda-panama
✓ Rainforest Alliance ✓ Organic ✓ Cup of Excellence
Por qué este enfoque
TOML versionado
Definiciones en código fuente, revisadas en PR. No se mezcla lógica de schema con runtime.
🔗
Metaobject reutilizable
Un productor ($app:producer) se vincula a múltiples productos. Un cambio se propaga a todos.
namespace: $app
Nunca namespace: app — es el error más común. El prefijo $app es resuelto por Shopify al gid de la app.