---
name: shopify-metacampos-masivos
description: "Guarda o borra metacampos en lote en productos, variantes o clientes, filtrados por etiqueta o colección. Úsala cuando necesites cargar el mismo dato estructurado (material, cuidados, especificaciones) en muchos registros a la vez."
---

## Propósito
Consulta los productos (o variantes, o clientes) que cumplen un filtro y guarda o borra en lote los valores de un metacampo. Sirve para actualizar datos estructurados como la composición del material, las instrucciones de cuidado, las especificaciones del producto o atributos personalizados que alimentan funciones de la tienda en línea.

## Requisitos
- Sesión autenticada de Shopify CLI: `shopify store auth --store <tu-tienda>.myshopify.com --scopes read_products,write_products`
- Las consultas se ejecutan con `shopify store execute`.
- Permisos (scopes) de API: `read_products`, `write_products`
- El namespace y la clave del metacampo deben existir ya o se crean la primera vez que se guarda un valor

## Parámetros

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|-------------|----------------|-------------|
| store | string | sí | — | Dominio de la tienda (p. ej., mitienda.myshopify.com) |
| resource_type | string | no | product | Recurso que se actualiza: `product`, `variant` o `customer` |
| filter | string | sí | — | Filtro de búsqueda (p. ej., `tag:summer-2026`, `vendor:Nike`) |
| namespace | string | sí | — | Namespace del metacampo (p. ej., `custom`) |
| key | string | sí | — | Clave del metacampo (p. ej., `material`) |
| value | string | no | — | Valor que se guarda. Si se omite y `action: delete`, el metacampo se borra |
| value_type | string | no | single_line_text_field | Tipo de metacampo (p. ej., `single_line_text_field`, `boolean`, `number_integer`) |
| action | string | no | set | `set` o `delete` |
| dry_run | bool | no | true | Muestra el resultado sin ejecutar mutaciones |
| format | string | no | human | Formato de salida: `human` o `json` |

## Seguridad

> ⚠️ `metafieldsSet` sobrescribe los valores existentes del metacampo: no los combina. `metafieldsDelete` elimina de forma permanente el valor del metacampo en el recurso. Ejecuta con `dry_run: true` para confirmar la lista de productos afectados y verificar que el namespace y la clave sean correctos antes de aplicar los cambios.

## Pasos

1. **OPERACIÓN:** `products` — consulta
   **Entradas:** `query: <filter>`, `first: 250`, selecciona los valores del metacampo para el namespace y la clave objetivo, y el cursor de paginación
   **Resultado esperado:** Productos con sus valores actuales del metacampo (como referencia); pagina hasta que `hasNextPage: false`

2. **OPERACIÓN:** `metafieldsSet` — mutación (si `action: set`)
   **Entradas:** Arreglo de objetos `{ ownerId, namespace, key, value, type }`
   **Resultado esperado:** `metafields { id, key, value }`, `userErrors`

3. **OPERACIÓN:** `metafieldsDelete` — mutación (si `action: delete`)
   **Entradas:** Arreglo de objetos `{ ownerId, namespace, key }`
   **Resultado esperado:** `deletedMetafields { ownerId }`, `userErrors`

## Operaciones GraphQL

```graphql
# products:query — validada con api_version 2025-01
query ProductsWithMetafield($query: String!, $namespace: String!, $key: String!, $after: String) {
  products(first: 250, after: $after, query: $query) {
    edges {
      node {
        id
        title
        metafield(namespace: $namespace, key: $key) {
          id
          value
          type
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

```graphql
# metafieldsSet:mutation — validada con api_version 2025-01
mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) {
  metafieldsSet(metafields: $metafields) {
    metafields {
      id
      namespace
      key
      value
      type
      owner {
        ... on Product {
          id
          title
        }
      }
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

```graphql
# metafieldsDelete:mutation — validada con api_version 2025-01
mutation MetafieldsDelete($metafields: [MetafieldIdentifierInput!]!) {
  metafieldsDelete(metafields: $metafields) {
    deletedMetafields {
      ownerId
      namespace
      key
    }
    userErrors {
      field
      message
    }
  }
}
```

## Seguimiento de la sesión

**Claude DEBE mostrar lo siguiente en cada etapa. Es obligatorio.**

**Al iniciar**, muestra:
```
╔══════════════════════════════════════════════╗
║  SKILL: shopify-metacampos-masivos           ║
║  Tienda: <dominio de la tienda>              ║
║  Inicio: <AAAA-MM-DD HH:MM UTC>              ║
╚══════════════════════════════════════════════╝
```

**Después de cada paso**, muestra:
```
[N/TOTAL] <CONSULTA|MUTACIÓN>  <OperationName>
          → Parámetros: <resumen breve de las entradas clave>
          → Resultado: <cantidad o desenlace>
```

Si `dry_run: true`, antepón `[SIMULACIÓN]` a cada paso de mutación y no lo ejecutes.

**Al terminar**, muestra:

Para `format: human` (predeterminado):
```
══════════════════════════════════════════════
RESUMEN DEL RESULTADO
  Registros encontrados:           <n>
  Metacampos guardados/borrados:   <n>
  Errores:                         <n>
  Archivo:                         metafield_update_<fecha>.csv
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "shopify-metacampos-masivos",
  "store": "<dominio>",
  "started_at": "<ISO8601>",
  "completed_at": "<ISO8601>",
  "dry_run": true,
  "namespace": "<ns>",
  "key": "<clave>",
  "action": "set",
  "outcome": {
    "matched": 0,
    "updated": 0,
    "errors": 0,
    "output_file": "metafield_update_<fecha>.csv"
  }
}
```

## Formato de salida
Archivo CSV `metafield_update_<AAAA-MM-DD>.csv` con las columnas:
`resource_type`, `resource_id`, `title`, `namespace`, `key`, `old_value`, `new_value`, `action`

## Manejo de errores
| Error | Causa | Solución |
|-------|-------|----------|
| `THROTTLED` | Se superó el límite de solicitudes de la API | Espera 2 segundos y reintenta hasta 3 veces |
| `userErrors`: tipo no válido | `value` no coincide con `value_type` | Registra el error, omite el registro y sigue |
| `userErrors`: namespace/clave no encontrados al borrar | El metacampo no existe | Regístralo como omitido (ya no estaba) |
| Ningún producto cumple el filtro | Filtro demasiado restringido | Termina con 0 coincidencias |

## Buenas prácticas
- `metafieldsSet` trabaja por lotes: la mutación acepta hasta 25 metacampos por llamada. La skill divide automáticamente los conjuntos grandes de productos en lotes.
- Verifica siempre que `namespace` y `key` coincidan con las definiciones de metacampos de tu tienda: un error de escritura crea metacampos huérfanos que no se conectan con ninguna función del tema.
- Para metacampos que se muestran en la tienda en línea (p. ej., en las plantillas de producto), confirma que el tema lee el namespace y la clave correctos antes de ejecutarla a gran escala.
- Usa `dry_run: true` para ver exactamente qué productos y qué valores actuales se verán afectados antes de sobrescribirlos.
