Un producto de Market puede tener un modelo 3D opcional. Tu tienda lee su URL pública desde la API externa del catálogo y muestra un visor interactivo: el cliente arrastra para girar y usa la rueda o el gesto de pinza para hacer zoom. Si no hay modelo (o el navegador no tiene WebGL), se muestra la imagen normal del producto.
Disponible desde Mailoo 1.34.13.
Subir un modelo en el panel
- Abre Panel → Proyectos → tu proyecto → integración Market → Productos y edita un producto.
- En la pestaña General busca el bloque Modelo 3D.
- Arrastra un archivo
.glba la zona (o haz clic y elígelo). Durante la subida se muestra una barra de progreso. - Pulsa Publicar (o Guardar como borrador) para guardar el modelo en el producto.

Tras la subida, el bloque muestra el nombre del archivo y el id del medio, un enlace Abrir (URL pública del modelo) y Eliminar. Subir otro archivo reemplaza el modelo; Eliminar lo desvincula al guardar.
Requisitos del archivo
- Formato: solo
.glb--- glTF 2.0 binario. Se valida el contenido (cabeceraglTF, versión 2); un archivo de otro formato renombrado a.glbse rechaza..gltfcon texturas externas,.obj,.fbxy.usdzno se aceptan: conviértelos antes a GLB (p. ej. Blender → Export glTF 2.0, formato glTF Binary). - Tamaño: hasta 50 MB por archivo (límite independiente de las imágenes). Para móviles, unos pocos MB con texturas comprimidas es lo ideal.
- Aislamiento: el modelo pertenece a la integración Market en la que se subió y solo puede asignarse a productos del mismo proyecto e integración.
URL externa (obsoleta)
Mientras no haya un modelo subido, el bloque ofrece también una URL externa del modelo (obsoleta): un enlace https público a .glb / .gltf. El campo está obsoleto; es preferible subir el archivo. Un modelo subido siempre tiene prioridad.
Qué recibe la tienda
Los productos de la API externa del catálogo (ver market-catalog-external-api{.interpreted-text role="doc"}) incluyen dos campos:
model3dUrl--- la URL efectiva del modelo onull. Para un modelo subido es la URL pública de Mailoo{baseUrl}/api/v1/public/models/{mediaId}; si no, la URL externa obsoleta.model3dMediaId--- id del GLB subido onull.
{
"id": "mailoo_dev_market_demo_product",
"attributes": { "name": "Mailoo Demo Widget" },
"model3dUrl": "https://api.mailoo.app/api/v1/public/models/yblrqe9jgdkv1a3g5913cptv",
"model3dMediaId": "yblrqe9jgdkv1a3g5913cptv"
}
El endpoint público del modelo no requiere clave API, así que el navegador lo carga directamente. Devuelve model/gltf-binary en streaming con CORS *, Cross-Origin-Resource-Policy: cross-origin y caché inmutable de un año (la URL cambia al reemplazar el modelo).
Mostrar el visor 3D en tu sitio
Sirve cualquier visor glTF. La implementación de referencia en la demo del integrador usa Google <model-viewer> <https://modelviewer.dev/> cargado bajo demanda:

'use client'
import { createElement, useEffect, useState } from 'react'
const MODEL_VIEWER_SRC =
'https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js'
export function Product3DViewer({ modelUrl, fallbackImageUrl, alt }: {
modelUrl?: string | null
fallbackImageUrl?: string | null
alt: string
}) {
const [ready, setReady] = useState(false)
useEffect(() => {
if (!modelUrl || customElements.get('model-viewer')) return setReady(!!modelUrl)
const s = document.createElement('script')
s.type = 'module'
s.src = MODEL_VIEWER_SRC
s.onload = () => setReady(true)
document.head.appendChild(s)
}, [modelUrl])
if (!modelUrl || !ready) {
return fallbackImageUrl ? <img src={fallbackImageUrl} alt={alt} /> : null
}
return createElement('model-viewer', {
src: modelUrl,
alt,
poster: fallbackImageUrl ?? undefined,
'camera-controls': '', // drag to rotate, scroll/pinch to zoom
'auto-rotate': '',
'touch-action': 'pan-y', // keep vertical page scroll on mobile
loading: 'lazy',
'shadow-intensity': '1',
style: { width: '100%', aspectRatio: '1 / 1' },
})
}
Uso con un producto de la API del catálogo:
<Product3DViewer
modelUrl={product.model3dUrl}
fallbackImageUrl={product.previewImageUrl}
alt={product.attributes.name}
/>
El componente completo de la demo (tests/integrator-demo/src/components/product-3d-viewer.tsx) añade:
- Carga diferida --- la biblioteca (~1 MB) se descarga solo cuando el visor entra en pantalla (
IntersectionObserver). - Respaldo a la imagen 2D si
model3dUrlestá vacío, no hay WebGL o el modelo no carga (eventoerror).
Solución de problemas
- «Only .glb (binary glTF 2.0) files are supported» / «File is not a valid GLB» --- exporta como glTF Binary (
.glb), glTF 2.0. - «Model too large» --- el archivo supera 50 MB; reduce polígonos o comprime texturas (p. ej.
gltf-transform optimize). - La tienda solo muestra la imagen --- comprueba que el producto esté publicado, que
model3dUrlno seanullen la respuesta de la API y que el navegador admita WebGL.