---
title: "Cortina de página"
description: "El banner corto que aparece en las páginas de Ring para ofrecer Añadir a pantalla de inicio o un producto anunciado, cómo lo descartan los visitantes, cómo los vendedores activan productos y cómo ganan comisión los autores de las páginas"
locale: "es"
---
# Cortina de página

La cortina de página es un banner estrecho (alrededor del 10% de la altura de la pantalla) que aparece cuando un visitante deja de desplazarse. Muestra uno de dos tipos de oferta: **Añadir a pantalla de inicio** para la app, o un **producto** que un vendedor ha decidido anunciar. En artículos de noticias y publicaciones del blog de miembros, un producto añadido desde la cortina puede generar una comisión para el autor de la página cuando el comprador paga más tarde.

> **Info**
> Usa las pestañas **Founder** / **Developer** de la barra lateral de la documentación para filtrar esta página. Las secciones compartidas se aplican a ambas audiencias.

> **Success**
> **Estado (2026-10-26):** Disponible en Layer 1 y configurable por clon mediante el bloque `curtain` de `ring-config.json`. La cola ahora respeta los descartes anteriores, así que un visitante que eligió Hoy no ya no ve el mismo banner en la página siguiente.

| Sin la cortina | Con la cortina |
|----------------|----------------|
| Los avisos de instalación dependen del navegador | Ring ofrece Añadir a pantalla de inicio por sí mismo, una vez por ventana de política |
| Los autores no ganan con los productos que mencionan | Los autores reciben crédito adicional en carritos pagados que empezaron en su página |
| Los vendedores pagan anuncios en otro sitio | Los vendedores activan un producto y fijan una comisión de autor del 1% al 10% |

### For founders

## Por qué importa para tu comunidad

Los autores atraen lectores; los vendedores quieren compradores. La cortina conecta a ambos sin un sistema de anuncios aparte. Un vendedor marca un producto, un autor lo enlaza o escribe sobre el mismo tema, y cuando un lector lo compra, el autor recibe una recompensa en crédito de la plataforma. El pago al vendedor no se reduce: la comisión se emite como crédito adicional.

  
- **[Noticias](/docs/features/news.md)** — Las páginas de artículos son donde aparecen las ofertas de productos.

  
- **[Blog de miembros](/docs/features/member-blog.md)** — Las publicaciones de miembros reciben las mismas ofertas y comisión de autor.

  
- **[Tienda](/docs/features/store.md)** — Los vendedores activan la publicidad en la cortina desde el formulario del producto.

### Escenarios típicos

- **Una bloguera gastronómica enlaza la miel de una granja** en un artículo. Los lectores ven la miel en la cortina, tocan Añadir al carrito y pagan dentro de 30 días. La bloguera recibe el 5% de esa línea como crédito.
- **Un visitante nuevo en el móvil** lee tres páginas. En una de ellas la cortina ofrece Añadir a pantalla de inicio. Toca Hoy no y no la vuelve a ver durante 24 horas.
- **Un lector toca No me interesa** en un producto. Ese producto no vuelve a aparecerle nunca.

```mermaid
flowchart LR
  A[Vendor enables advertise] --> B[Article page]
  B --> C[Curtain offer]
  C -->|Add to cart| D[Signed touch stored]
  D --> E[Paid order within 30 days]
  E --> F[Author gets credit]
```

### Dónde ver los resultados

- **Vendedores:** la página de ganancias muestra un embudo de la cortina de 7 días: mostrado, mostrado de nuevo, CTA, hoy no, no me interesa, desplazado, pagado y créditos emitidos.
- **Autores:** My News (`/my-news`) muestra el mismo embudo de 7 días para sus páginas más los créditos de cortina ganados.
- **Operadores:** la página de analítica del administrador muestra el mismo embudo para todo el clon, junto a la política de cortina activa.

### For developers

## Configuración

`ring-config.template.json` incluye estos valores por defecto. Sobrescribe cualquier clave en el `ring-config.json` de tu clon. Los valores los lee `getCurtainPolicy()` en `lib/ring-config-core.ts` y los valida `parseCurtainPolicy` en `features/curtain/lib/policy.ts`.

| Clave | Por defecto | Valores permitidos |
|-------|-------------|--------------------|
| `curtain.enabled` | `true` | `false` desactiva todas las ofertas |
| `curtain.productSource` | `page_then_pool` | `page_then_pool`, `page_only`, `pool_only` |
| `curtain.maxImpressionsPerDay` | `5` | de 1 a 50 por oferta, por día UTC |
| `curtain.notTodayHours` | `24` | de 1 a 168 |

{`{
  "curtain": {
    "enabled": true,
    "productSource": "page_only",
    "maxImpressionsPerDay": 3,
    "notTodayHours": 48
  }
}`}

## Cómo se eligen las ofertas

`requestCurtainDrop` en `features/curtain/actions.ts` devuelve hasta tres ofertas (`CURTAIN_QUEUE_MAX`):

1. Se omite por completo cuando la política está desactivada o la ruta empieza por `/admin`, `/login`, `/register`, `/auth`, `/vendor` o `/store/checkout`.
2. Ofertas de productos solo en páginas que pasan un `newsArticleId` mediante `CurtainPageProvider` (artículos de noticias y publicaciones del blog de miembros). El artículo debe estar publicado y ser visible para el lector según `canViewNewsArticle`.
3. Los productos de **página** son enlaces `/store/` encontrados en el cuerpo del artículo. Los productos del **pool** son productos activos con `curtainAdvertiseEnabled`. Cada uno debe estar anunciado, activo, tener precio, no ser un producto propio del vendedor que mira y no estar suprimido.
4. Orden: primero los productos enlazados, después la coincidencia de tema con la categoría y las etiquetas del artículo, después menos impresiones hoy.
5. Un hueco libre se llena con Añadir a pantalla de inicio cuando el navegador no está ejecutando ya la app instalada.

`curtain-host.tsx` muestra la cola y aplica `canShowOffer` a cada elemento en cola, lo que corrige que volvieran los banners descartados.

## Respuestas del visitante

| Respuesta | Efecto |
|-----------|--------|
| CTA | Añadir al carrito (producto) o aviso de instalación (A2HS) |
| Hoy no | Suprimido durante `notTodayHours` desde ahora |
| No me interesa | Suprimido para siempre para esa oferta |
| Desplazarse | Se registra, sin supresión |

Las preferencias se guardan en `localStorage` (`ring_curtain_prefs`) y, para miembros con sesión iniciada, en la tabla `curtain_preferences` (migración `050`, parte de `schema.sql`) mediante `syncCurtainPrefs`.

## Atribución y comisión

- Cada oferta de producto lleva un `offerToken` HMAC de `features/curtain/lib/offer-token.ts`, firmado con `AUTH_SECRET`. Vincula oferta, producto, autor y artículo.
- Los toques de CTA se guardan en la cookie `ring_curtain_attr` y en el almacenamiento (ventana de 30 días, como máximo 12 toques).
- El checkout conserva solo los toques que pasan `verifyCurtainTouches`. El autor y el porcentaje salen del token y del producto actual, nunca del navegador.
- Tras el pago, `mintCurtainAuthorCommission` en `features/curtain/services/commission.ts` añade crédito al autor: subtotal de la línea por el porcentaje del producto (de 1 a 10, por defecto 5). Omite las compras propias, al referente del pedido y los duplicados, y solo se ejecuta cuando las recompensas de crédito están activadas.
- Los eventos `curtain_shown`, `curtain_response`, `curtain_cta`, `curtain_suppress` y `curtain_paid` alimentan `getCurtainFunnel` en `features/analytics/lib/curtain-analytics.ts`.

## Activación por el vendedor

El formulario de producto del vendedor incluye `AdvertiseProductWidget` (`features/curtain/components/advertise-product-widget.tsx`). Escribe `curtainAdvertise: { enabled, commissionPercent }` y `curtainAdvertiseEnabled` en el producto. Un producto sin precio no se puede anunciar.

## Preguntas frecuentes

### Impacto

#### ¿La comisión sale del pago al vendedor?

No. Es crédito adicional emitido al autor, registrado con la fuente `curtain_author`.

### Migración

#### ¿Necesito una migración?

No en una instalación nueva. Las bases de datos existentes necesitan `050_curtain_offers.sql` para `curtain_preferences` y el índice de analítica.

### Operaciones

#### ¿Cómo desactivo la cortina en un clon?

Pon `"curtain": { "enabled": false }` en el `ring-config.json` de ese clon y vuelve a compilar.

  
- [features/store](/docs/features/store.md) — Depende de: productos, carrito y pedidos pagados que activan la comisión.

  
- [features/news](/docs/features/news.md) — Mismo flujo: páginas de artículos que alojan ofertas de productos.

  
- [features/member-blog](/docs/features/member-blog.md) — Mismo flujo: las publicaciones de miembros alojan las mismas ofertas.

  
- [features/rewards](/docs/features/rewards.md) — Ver también: recompensas de crédito, que deben estar activadas para la comisión.

  
- [features/refcodes](/docs/features/refcodes.md) — Ver también: atribución de referidos, que comparte la ventana de 30 días.
