> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Plantillas HTML para mensajes dentro de la aplicación

> Plantillas HTML de copiar y pegar que puedes usar en los Mensajes Dentro de la Aplicación de OneSignal, además de la configuración requerida y problemas comunes.

Utiliza estas plantillas HTML de copiar y pegar para construir mensajes dentro de la aplicación personalizados de OneSignal más rápido.

Nuestro Editor HTML de Mensajes Dentro de la Aplicación te permite controlar completamente el diseño y comportamiento de tu mensaje dentro de la aplicación usando HTML, CSS y JavaScript. El editor **no incluye plantillas integradas**, pero esta página proporciona **ejemplos listos para usar** que puedes pegar en el editor y personalizar.

<Note>
  Estas plantillas se ejecutan dentro de un webview de mensaje dentro de la aplicación. Para cerrar mensajes, abrir URLs, etiquetar usuarios y capturar clics, usa la [API JS de Mensaje Dentro de la Aplicación](./in-app-message-api).
</Note>

## Requisitos previos

Antes de empezar, te recomendamos revisar:

* La página de [Resumen de Mensajes Dentro de la Aplicación](./in-app-messages-setup).
* La página de [Diseña tu Mensaje Dentro de la Aplicación con el Editor HTML](./design-your-in-app-message-with-html).

<Warning>
  No pongas secretos (claves API, tokens) en el código de plantillas. Trata todas las entradas de mensajes dentro de la aplicación como no confiables y valídalas en tu aplicación o backend.
</Warning>

## Cómo usar las plantillas

1. En OneSignal, ve a **Mensajes > Dentro de la Aplicación > Nuevo Mensaje Dentro de la Aplicación**.
2. Selecciona el **editor HTML**.
3. Encuentra una plantilla abajo.
4. Copia el HTML completo del bloque de código y pégalo en el editor.
5. Actualiza los marcadores de posición (URLs, endpoints, fechas y copia).
6. Prueba en un dispositivo real, luego publica.

## Plantillas disponibles

<Card title="Formulario de Recolección de Correo" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/email-form.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=d74293c6b7c0c2ed0694078d41a8c1c8" href="#email-form" width="1258" height="708" data-path="images/html-iam/email-form.png">
  Pregunta por el correo del usuario y envíalo a tu aplicación mediante nombre de clic.
</Card>

<Card title="Formulario de Recolección de Números de Teléfono" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/sms-form.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=d5444750f75c638f9aacc4cadc8ce8e3" href="#sms-form" width="1251" height="704" data-path="images/html-iam/sms-form.png">
  Pregunta y obtén consentimiento para enviar SMS. Incluye número de teléfono en formato E.164 y envíalo a tu aplicación mediante nombre de clic.
</Card>

<Card title="Encuesta de Lista de Verificación" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/checklist-survey.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=e35945ecfefabdb013053aa814c3618d" href="#checklist-survey" width="574" height="322" data-path="images/html-iam/checklist-survey.png">
  Encuesta de selección múltiple que puedes enviar a tu backend o convertir en etiquetas.
</Card>

<Card title="Cuenta Regresiva" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/count_down.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=bcc786162ca0f4837c244f0d7f03097d" href="#countdown" width="1820" height="1024" data-path="images/html-iam/count_down.png">
  Temporizador de cuenta regresiva para promociones sensibles al tiempo.
</Card>

<Card title="Rueda Promocional" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/promo-wheel.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=dfd0aa50f5981774267644acb17da817" href="#promo-wheel" width="574" height="322" data-path="images/html-iam/promo-wheel.png">
  Experiencia promocional de girar para ganar (personaliza el manejo de promociones).
</Card>

<Card title="Modal de Quiz" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/quiz_modal.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=66399edf105d0799bdfab78412a60744" href="#quiz-modal" width="1820" height="1024" data-path="images/html-iam/quiz_modal.png">
  Experiencia de quiz que puede etiquetar usuarios con su puntuación.
</Card>

<Card title="Encuesta de Calificación" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/ranking-survey.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=42cfa0b554dbfe1f59f61c47306f8460" href="#ranking-survey" width="574" height="322" data-path="images/html-iam/ranking-survey.png">
  Encuesta de calificación de 1–5 (envía a tu endpoint o etiqueta usuario).
</Card>

<Card title="Reproductor de Audio/Video" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/ui-ui.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=cf9bdf607dda82687faa1c874fddebb4" href="#audio/video-player" width="574" height="322" data-path="images/html-iam/ui-ui.png">
  UI simple de vista previa de audio para un archivo MP3 directo.
</Card>

<Card title="Deslizamiento Vertical" img="https://mintcdn.com/onesignal/gVwen8HnVQfsFC-e/images/html-iam/vertical-swiping.png?fit=max&auto=format&n=gVwen8HnVQfsFC-e&q=85&s=3cb4a092cf2e4bb14bee214a0c22c58b" href="#vertical-swiping" width="574" height="322" data-path="images/html-iam/vertical-swiping.png">
  Tour de incorporación o características de múltiples diapositivas con deslizamiento vertical.
</Card>

***

### Formulario de correo

Recopila [Suscripciones](./subscriptions) de correo a través de un mensaje dentro de la aplicación.

Cómo funciona este formulario:

1. El usuario ingresa una dirección de correo y marca una casilla de consentimiento.
2. Al enviar, se llama a la API Crear Usuario de OneSignal para crear la Suscripción de correo en tu aplicación.
3. Además, la plantilla llama `OneSignalIamApi.addClickName(e, email)` que pasa la dirección de correo al Listener de Clic de Mensaje Dentro de la Aplicación de nuestro SDK.
4. Dentro de tu aplicación, puedes agregar el Listener de Clic de Mensaje Dentro de la Aplicación para leer el nombre del clic y pasar el correo al método `addEmail` de nuestro SDK.

Puedes notar que tanto el paso 2 como el paso 4 involucran crear la Suscripción de correo.

* El paso 2 no requiere agregar código directamente en la aplicación pero tampoco agrega la Suscripción de correo al usuario si llamaste al método `login`.
* El paso 4 requiere código adicional (el Listener de Clic de Mensaje Dentro de la Aplicación) pero también agrega la Suscripción de correo al usuario si llamaste al método `login`.

<Accordion title="Código HTML del Formulario de Correo">
  \*\*Reemplaza `YOUR_APP_ID` con tu ID de Aplicación de OneSignal que se encuentra en [Configuración > Claves e IDs](./keys-and-ids).

  ```html theme={null}
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <!-- Prevenir zoom de iOS en el foco del input -->
      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
      <style>
          /* ===== RESET ===== */
          * {
              box-sizing: border-box;
              margin: 0;
              padding: 0;
          }
          
          /* ===== BASE ===== */
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: transparent;
              display: flex;
              justify-content: center;
              align-items: center;
              min-height: 100vh;
              padding: 20px;
          }
          
          /* ===== CARD ===== */
          .container {
              position: relative;
              background: #ffffff;
              border-radius: 16px;
              padding: 32px 24px;
              max-width: 340px;
              width: 100%;
              box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
              text-align: center;
              overflow: hidden;
          }
          
          /* ===== BOTÓN CERRAR ===== */
          .close-btn {
              position: absolute;
              top: 12px;
              right: 12px;
              background: none;
              border: none;
              font-size: 24px;
              color: #999;
              cursor: pointer;
              padding: 4px 8px;
              line-height: 1;
          }
          
          .close-btn:hover {
              color: #333;
          }
          
          /* ===== TIPOGRAFÍA ===== */
          h1 {
              font-size: 22px;
              font-weight: 600;
              color: #333;
              margin-bottom: 8px;
          }
          
          p {
              font-size: 14px;
              color: #666;
              margin-bottom: 24px;
              line-height: 1.5;
          }
          
          /* ===== INPUT DE CORREO ===== */
          .email-input {
              width: 100%;
              padding: 14px 12px;
              font-size: 16px; /* Prevenir zoom de iOS */
              border: 2px solid #e0e0e0;
              border-radius: 10px;
              margin-bottom: 16px;
              outline: none;
              transition: border-color 0.2s;
              touch-action: manipulation; /* Mejorar experiencia móvil */
          }
          
          .email-input:focus {
              border-color: #007AFF;
          }
          
          .email-input::placeholder {
              color: #aaa;
          }
          
          /* ===== CHECKBOX DE CONSENTIMIENTO ===== */
          .consent-wrapper {
              display: flex;
              align-items: flex-start;
              gap: 10px;
              text-align: left;
              margin-bottom: 16px;
          }
          
          .consent-wrapper input[type="checkbox"] {
              width: 18px;
              height: 18px;
              margin-top: 2px;
              cursor: pointer;
              flex-shrink: 0;
          }
          
          .consent-wrapper label {
              font-size: 13px;
              color: #666;
              line-height: 1.4;
              cursor: pointer;
          }
          
          /* ===== BOTÓN ENVIAR ===== */
          .submit-btn {
              width: 100%;
              padding: 14px 24px;
              font-size: 16px;
              font-weight: 600;
              color: #fff;
              background: #007AFF;
              border: none;
              border-radius: 10px;
              cursor: pointer;
              transition: background 0.2s, opacity 0.2s;
          }
          
          .submit-btn:hover {
              background: #0056b3;
          }
          
          .submit-btn:disabled {
              background: #ccc;
              cursor: not-allowed;
              opacity: 0.7;
          }
          
          /* ===== MENSAJES DE ESTADO ===== */
          .error-msg,
          .success-msg {
              font-size: 12px;
              margin-top: -12px;
              margin-bottom: 12px;
              display: none;
          }
          
          .error-msg {
              color: #dc3545;
          }
          
          .success-msg {
              color: #28a745;
          }
          
          /* ===== RESPONSIVE ===== */
          @media (max-width: 480px) {
              body {
                  padding: 15px;
              }
              
              .container {
                  padding: 24px 20px;
              }
              
              h1 {
                  font-size: 20px;
              }
          }
      </style>
  </head>
  <body>
      <div class="container">
          <!-- Botón cerrar -->
          <button class="close-btn" onclick="OneSignalIamApi.close(event)">&times;</button>
          
          <!-- Título y descripción -->
          <h1>Obtén Actualizaciones Exclusivas</h1>
          <p>Ingresa tu correo para recibir las últimas noticias y ofertas especiales.</p>
          
          <!-- Formulario -->
          <form id="emailForm">
              <!-- Mensaje de error -->
              <div class="error-msg" id="errorMsg">Por favor ingresa un correo válido</div>
              
              <!-- Mensaje de éxito -->
              <div class="success-msg" id="successMsg">¡Gracias! Te contactaremos pronto.</div>
              
              <!-- Input de correo -->
              <input 
                  type="email" 
                  class="email-input" 
                  id="emailInput" 
                  placeholder="Ingresa tu correo" 
                  required
              />
              
              <!-- Checkbox de consentimiento -->
              <div class="consent-wrapper">
                  <input type="checkbox" id="consent" required />
                  <label for="consent">
                      Acepto recibir actualizaciones por correo y contenido promocional. Puedes cancelar la suscripción en cualquier momento.
                  </label>
              </div>
              
              <!-- Botón enviar -->
              <button type="submit" class="submit-btn" id="submitBtn">
                  Suscribirse a Actualizaciones
              </button>
          </form>
      </div>

      <script>
          // Esperar carga del DOM
          document.addEventListener('DOMContentLoaded', function() {
              const form = document.getElementById('emailForm');
              const emailInput = document.getElementById('emailInput');
              const consentCheckbox = document.getElementById('consent');
              const submitBtn = document.getElementById('submitBtn');
              const errorMsg = document.getElementById('errorMsg');
              const successMsg = document.getElementById('successMsg');

              // Función de validación de correo
              function isValidEmail(email) {
                  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                  return emailRegex.test(email);
              }

              // Mostrar mensaje de error
              function showError(message) {
                  errorMsg.textContent = message;
                  errorMsg.style.display = 'block';
                  successMsg.style.display = 'none';
              }

              // Mostrar mensaje de éxito
              function showSuccess(message) {
                  successMsg.textContent = message;
                  successMsg.style.display = 'block';
                  errorMsg.style.display = 'none';
              }

              // Ocultar mensajes
              function hideMessages() {
                  errorMsg.style.display = 'none';
                  successMsg.style.display = 'none';
              }

              // Validación de entrada y actualización de UI
              function validateForm() {
                  const email = emailInput.value.trim();
                  const isEmailValid = isValidEmail(email);
                  const isConsentGiven = consentCheckbox.checked;
                  
                  submitBtn.disabled = !(isEmailValid && isConsentGiven);
                  
                  if (email && !isEmailValid) {
                      showError('Por favor ingresa un correo válido');
                  } else if (!email || isEmailValid) {
                      hideMessages();
                  }
              }

              // Event listeners
              emailInput.addEventListener('input', validateForm);
              emailInput.addEventListener('blur', validateForm);
              consentCheckbox.addEventListener('change', validateForm);

              // Manejo de envío de formulario
              form.addEventListener('submit', async function(e) {
                  e.preventDefault();
                  
                  const email = emailInput.value.trim();
                  
                  if (!isValidEmail(email)) {
                      showError('Por favor ingresa un correo válido');
                      return;
                  }
                  
                  if (!consentCheckbox.checked) {
                      showError('Por favor acepta recibir actualizaciones por correo');
                      return;
                  }

                  // Deshabilitar formulario
                  submitBtn.disabled = true;
                  submitBtn.textContent = 'Procesando...';

                  try {
                      // Paso 2: Crear suscripción de correo mediante REST API
                      const response = await fetch('https://api.onesignal.com/apps/YOUR_APP_ID/users', {
                          method: 'POST',
                          headers: {
                              'Content-Type': 'application/json',
                          },
                          body: JSON.stringify({
                              properties: {
                                  tags: {
                                      email_collected_via_iam: 'true'
                                  }
                              },
                              subscriptions: [
                                  {
                                      type: 'Email',
                                      token: email,
                                      enabled: true
                                  }
                              ]
                          })
                      });

                      if (response.ok) {
                          showSuccess('¡Gracias! Te contactaremos pronto.');
                      } else {
                          throw new Error('Fallo en suscripción');
                      }

                      // Paso 3: Pasar correo al SDK mediante nombre de clic
                      OneSignalIamApi.addClickName(e, email);

                      // Retrasar cierre del mensaje
                      setTimeout(() => {
                          OneSignalIamApi.close(e);
                      }, 2000);

                  } catch (error) {
                      console.error('Error de suscripción de correo:', error);
                      showError('Ocurrió un error, por favor intenta de nuevo');
                      
                      // Re-habilitar formulario
                      submitBtn.disabled = false;
                      submitBtn.textContent = 'Suscribirse a Actualizaciones';
                  }
              });

              // Validación inicial
              validateForm();
          });
      </script>
  </body>
  </html>
  ```
</Accordion>

**Requisitos del Paso 4:**

1. Mantén la llamada [addClickName](./in-app-message-api#click-name) en tu manejador de envío HTML.
2. Usa el [Listener de Clic de Mensaje Dentro de la Aplicación](./mobile-sdk-reference#addclicklistener-in-app) de nuestro SDK para leer la entrada.
3. Cuando el nombre del clic se vea como un correo, llama al método [addEmail](./mobile-sdk-reference#addemail-,-removeemail) en el Listener de Clic de Mensaje Dentro de la Aplicación.

**Ejemplo usando el Listener de Clic de Mensaje Dentro de la Aplicación y método addEmail:**

```swift theme={null}
// Ejemplo de manejador de clic de mensaje dentro de la aplicación para capturar correos y teléfonos en mensajes HTML dentro de la aplicación
class InAppMessageClickHandler: NSObject, OSInAppMessageClickListener {
    func onClick(event: OSInAppMessageClickEvent) {
        // Obtener el nombre del clic (action ID) del evento
        let clickName = event.result.actionId
        print("Mensaje dentro de la aplicación clicado con actionId: \(clickName ?? "nil")")
        
        guard let value = clickName else { return }
        
        // Verificar si el nombre del clic se ve como una dirección de correo
        if value.contains("@") && value.contains(".") {
            OneSignal.User.addEmail(value)
            print("Correo agregado a OneSignal: \(value)")
        }
        // Verificar si el nombre del clic se ve como un número de teléfono E.164 (+1XXXXXXXXXX)
        else if value.hasPrefix("+") && value.count >= 11 {
            OneSignal.User.addSms(value)
            print("SMS agregado a OneSignal: \(value)")
        }
    }
}
```

***

### Formulario SMS

Recopila [Suscripciones](./subscriptions) SMS a través de un mensaje dentro de la aplicación.

Cómo funciona este formulario:

1. El usuario selecciona su código de país, ingresa un número de 10 dígitos y marca una casilla de consentimiento.
2. Al enviar, se llama a la API Crear Usuario de OneSignal para crear la Suscripción SMS en tu aplicación.
3. Además, la plantilla llama `OneSignalIamApi.addClickName(e, e164Phone)` que pasa el número de teléfono al Listener de Clic de Mensaje Dentro de la Aplicación de nuestro SDK.
4. Dentro de tu aplicación, puedes agregar el Listener de Clic de Mensaje Dentro de la Aplicación para leer el nombre del clic y pasar el número de teléfono al método `addSms` de nuestro SDK.

Puedes notar que tanto el paso 2 como el paso 4 involucran crear la Suscripción SMS.

* El paso 2 no requiere agregar código directamente en la aplicación pero tampoco agrega la Suscripción SMS al usuario si llamaste al método `login`.
* El paso 4 requiere código adicional (el Listener de Clic de Mensaje Dentro de la Aplicación) pero también agrega la Suscripción SMS al usuario si llamaste al método `login`.

<Accordion title="Código HTML del Formulario SMS">
  \*\*Reemplaza `YOUR_APP_ID` con tu ID de Aplicación de OneSignal que se encuentra en [Configuración > Claves e IDs](./keys-and-ids).

  ```html theme={null}
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
      <style>
          /* ===== RESET ===== */
          * {
              box-sizing: border-box;
              margin: 0;
              padding: 0;
          }
          
          /* ===== BASE ===== */
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: transparent;
              display: flex;
              justify-content: center;
              align-items: center;
              min-height: 100vh;
              padding: 20px;
          }
          
          /* ===== CARD ===== */
          .container {
              position: relative;
              background: #ffffff;
              border-radius: 16px;
              padding: 32px 24px;
              max-width: 340px;
              width: 100%;
              box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
              text-align: center;
              overflow: hidden;
          }
          
          /* ===== BOTÓN CERRAR ===== */
          .close-btn {
              position: absolute;
              top: 12px;
              right: 12px;
              background: none;
              border: none;
              font-size: 24px;
              color: #999;
              cursor: pointer;
              padding: 4px 8px;
              line-height: 1;
          }
          
          .close-btn:hover {
              color: #333;
          }
          
          /* ===== TIPOGRAFÍA ===== */
          h1 {
              font-size: 22px;
              font-weight: 600;
              color: #333;
              margin-bottom: 8px;
          }
          
          p {
              font-size: 14px;
              color: #666;
              margin-bottom: 24px;
              line-height: 1.5;
          }
          
          /* ===== INPUT DE TELÉFONO ===== */
          .phone-input-wrapper {
              display: flex;
              align-items: center;
              gap: 8px;
              margin-bottom: 16px;
              width: 100%;
          }
          
          .country-select {
              display: flex;
              align-items: center;
              padding: 14px 8px;
              background: #f5f5f5;
              border: 2px solid #e0e0e0;
              border-radius: 10px;
              font-size: 14px;
              color: #333;
              flex-shrink: 0;
              cursor: pointer;
              outline: none;
              appearance: none;
              -webkit-appearance: none;
              background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
              background-repeat: no-repeat;
              background-position: right 8px center;
              padding-right: 24px;
          }
          
          .country-select:focus {
              border-color: #007AFF;
          }
          
          .phone-input {
              flex: 1;
              min-width: 0;
              padding: 14px 12px;
              font-size: 16px;
              border: 2px solid #e0e0e0;
              border-radius: 10px;
              outline: none;
              transition: border-color 0.2s;
              width: 100%;
              touch-action: manipulation;
          }
          
          .phone-input:focus {
              border-color: #007AFF;
          }
          
          .phone-input::placeholder {
              color: #aaa;
          }
          
          /* ===== CHECKBOX DE CONSENTIMIENTO ===== */
          .consent-wrapper {
              display: flex;
              align-items: flex-start;
              gap: 10px;
              text-align: left;
              margin-bottom: 16px;
          }
          
          .consent-wrapper input[type="checkbox"] {
              width: 18px;
              height: 18px;
              margin-top: 2px;
              cursor: pointer;
              flex-shrink: 0;
          }
          
          .consent-wrapper label {
              font-size: 13px;
              color: #666;
              line-height: 1.4;
              cursor: pointer;
          }
          
          /* ===== BOTÓN ENVIAR ===== */
          .submit-btn {
              width: 100%;
              padding: 14px 24px;
              font-size: 16px;
              font-weight: 600;
              color: #fff;
              background: #007AFF;
              border: none;
              border-radius: 10px;
              cursor: pointer;
              transition: background 0.2s, opacity 0.2s;
          }
          
          .submit-btn:hover {
              background: #0056b3;
          }
          
          .submit-btn:disabled {
              background: #ccc;
              cursor: not-allowed;
              opacity: 0.7;
          }
          
          /* ===== MENSAJES DE ESTADO ===== */
          .error-msg,
          .success-msg {
              font-size: 12px;
              margin-top: -12px;
              margin-bottom: 12px;
              display: none;
          }
          
          .error-msg {
              color: #dc3545;
          }
          
          .success-msg {
              color: #28a745;
          }
          
          /* ===== RESPONSIVE ===== */
          @media (max-width: 480px) {
              body {
                  padding: 15px;
              }
              
              .container {
                  padding: 24px 20px;
              }
              
              h1 {
                  font-size: 20px;
              }
              
              .phone-input-wrapper {
                  flex-direction: column;
              }
              
              .country-select {
                  width: 100%;
              }
          }
      </style>
  </head>
  <body>
      <div class="container">
          <!-- Botón cerrar -->
          <button class="close-btn" onclick="OneSignalIamApi.close(event)">&times;</button>
          
          <!-- Título y descripción -->
          <h1>Obtén Actualizaciones SMS</h1>
          <p>Ingresa tu número de teléfono para recibir actualizaciones importantes e información promocional.</p>
          
          <!-- Formulario -->
          <form id="smsForm">
              <!-- Mensaje de error -->
              <div class="error-msg" id="errorMsg">Por favor ingresa un número de teléfono válido</div>
              
              <!-- Mensaje de éxito -->
              <div class="success-msg" id="successMsg">¡Gracias! Te contactaremos pronto.</div>
              
              <!-- Input de teléfono -->
              <div class="phone-input-wrapper">
                  <select class="country-select" id="countrySelect">
                      <option value="+1">🇺🇸 +1</option>
                      <option value="+44">🇬🇧 +44</option>
                      <option value="+33">🇫🇷 +33</option>
                      <option value="+49">🇩🇪 +49</option>
                      <option value="+34">🇪🇸 +34</option>
                      <option value="+39">🇮🇹 +39</option>
                      <option value="+81">🇯🇵 +81</option>
                      <option value="+82">🇰🇷 +82</option>
                      <option value="+86">🇨🇳 +86</option>
                      <option value="+91">🇮🇳 +91</option>
                      <option value="+61">🇦🇺 +61</option>
                      <option value="+55">🇧🇷 +55</option>
                      <option value="+52">🇲🇽 +52</option>
                      <option value="+7">🇷🇺 +7</option>
                      <option value="+90">🇹🇷 +90</option>
                  </select>
                  <input 
                      type="tel" 
                      class="phone-input" 
                      id="phoneInput" 
                      placeholder="Ingresa número de teléfono" 
                      required
                  />
              </div>
              
              <!-- Checkbox de consentimiento -->
              <div class="consent-wrapper">
                  <input type="checkbox" id="consent" required />
                  <label for="consent">
                      Acepto recibir actualizaciones SMS y contenido promocional. Se aplican tarifas estándar de mensajes. Puedes cancelar la suscripción en cualquier momento.
                  </label>
              </div>
              
              <!-- Botón enviar -->
              <button type="submit" class="submit-btn" id="submitBtn">
                  Suscribirse a Actualizaciones SMS
              </button>
          </form>
      </div>

      <script>
          // Esperar carga del DOM
          document.addEventListener('DOMContentLoaded', function() {
              const form = document.getElementById('smsForm');
              const countrySelect = document.getElementById('countrySelect');
              const phoneInput = document.getElementById('phoneInput');
              const consentCheckbox = document.getElementById('consent');
              const submitBtn = document.getElementById('submitBtn');
              const errorMsg = document.getElementById('errorMsg');
              const successMsg = document.getElementById('successMsg');

              // Función de validación de teléfono
              function isValidPhone(phone) {
                  // Validación básica: 7-15 dígitos, posiblemente incluyendo guiones, espacios o paréntesis
                  const phoneRegex = /^[\d\s\-\(\)]{7,15}$/;
                  return phoneRegex.test(phone.replace(/\s/g, ''));
              }

              // Formatear a formato E.164
              function formatToE164(countryCode, phone) {
                  // Quitar todos los caracteres no numéricos
                  const cleanPhone = phone.replace(/\D/g, '');
                  return countryCode + cleanPhone;
              }

              // Mostrar mensaje de error
              function showError(message) {
                  errorMsg.textContent = message;
                  errorMsg.style.display = 'block';
                  successMsg.style.display = 'none';
              }

              // Mostrar mensaje de éxito
              function showSuccess(message) {
                  successMsg.textContent = message;
                  successMsg.style.display = 'block';
                  errorMsg.style.display = 'none';
              }

              // Ocultar mensajes
              function hideMessages() {
                  errorMsg.style.display = 'none';
                  successMsg.style.display = 'none';
              }

              // Validación de formulario y actualización de UI
              function validateForm() {
                  const phone = phoneInput.value.trim();
                  const isPhoneValid = isValidPhone(phone);
                  const isConsentGiven = consentCheckbox.checked;
                  
                  submitBtn.disabled = !(isPhoneValid && isConsentGiven);
                  
                  if (phone && !isPhoneValid) {
                      showError('Por favor ingresa un número de teléfono válido');
                  } else if (!phone || isPhoneValid) {
                      hideMessages();
                  }
              }

              // Event listeners
              phoneInput.addEventListener('input', validateForm);
              phoneInput.addEventListener('blur', validateForm);
              consentCheckbox.addEventListener('change', validateForm);
              countrySelect.addEventListener('change', validateForm);

              // Manejo de envío de formulario
              form.addEventListener('submit', async function(e) {
                  e.preventDefault();
                  
                  const phone = phoneInput.value.trim();
                  const countryCode = countrySelect.value;
                  
                  if (!isValidPhone(phone)) {
                      showError('Por favor ingresa un número de teléfono válido');
                      return;
                  }
                  
                  if (!consentCheckbox.checked) {
                      showError('Por favor acepta recibir actualizaciones SMS');
                      return;
                  }

                  // Deshabilitar formulario
                  submitBtn.disabled = true;
                  submitBtn.textContent = 'Procesando...';

                  const e164Phone = formatToE164(countryCode, phone);

                  try {
                      // Paso 2: Crear suscripción SMS mediante REST API
                      const response = await fetch('https://api.onesignal.com/apps/YOUR_APP_ID/users', {
                          method: 'POST',
                          headers: {
                              'Content-Type': 'application/json',
                          },
                          body: JSON.stringify({
                              properties: {
                                  tags: {
                                      sms_collected_via_iam: 'true'
                                  }
                              },
                              subscriptions: [
                                  {
                                      type: 'SMS',
                                      token: e164Phone,
                                      enabled: true
                                  }
                              ]
                          })
                      });

                      if (response.ok) {
                          showSuccess('¡Gracias! Te contactaremos pronto.');
                      } else {
                          throw new Error('Fallo en suscripción');
                      }

                      // Paso 3: Pasar número de teléfono al SDK mediante nombre de clic
                      OneSignalIamApi.addClickName(e, e164Phone);

                      // Retrasar cierre del mensaje
                      setTimeout(() => {
                          OneSignalIamApi.close(e);
                      }, 2000);

                  } catch (error) {
                      console.error('Error de suscripción SMS:', error);
                      showError('Ocurrió un error, por favor intenta de nuevo');
                      
                      // Re-habilitar formulario
                      submitBtn.disabled = false;
                      submitBtn.textContent = 'Suscribirse a Actualizaciones SMS';
                  }
              });

              // Validación inicial
              validateForm();
          });
      </script>
  </body>
  </html>
  ```
</Accordion>

***

### Encuesta de Lista de Verificación

Encuesta de selección múltiple que envía resultados a tu backend.

* Establece tu endpoint en `handleSurveyAnswer()`.
* Actualiza los valores `name` de los checkboxes y etiquetas para coincidir con tu pregunta.

<Note>
  Si dejas `var url = ""`, la solicitud fallará. Establece un endpoint real o reemplaza `fetch()` con etiquetado (ejemplo abajo).
</Note>

<Accordion title="Código HTML">
  ```html theme={null}
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta http-equiv="X-UA-Compatible" content="ie=edge" />
      <title>Mensaje Dentro de la Aplicación OneSignal</title>
      <!-- Google Fonts -->
      <link rel="preconnect" href="https://fonts.googleapis.com" />
      <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
      <link
        href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@500;700&family=Raleway:wght@500;700&display=swap"
        rel="stylesheet"
      />
      <style>
        * {
          box-sizing: border-box;
        }

        body {
          margin: 0;
          padding-top: var(--safe-area-inset-top);
          padding-right: var(--safe-area-inset-right);
          padding-bottom: calc(var(--safe-area-inset-bottom) + 20px);
          padding-left: var(--safe-area-inset-left);
          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
            Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
          display: flex;
          align-items: center;
        }

        .center-modal {
          position: relative;
          background: #fae8cd;
          margin: 18px;
          border-radius: 8px;
          display: flex;
          flex-direction: column;
          justify-content: center;
          height: 85%;
          max-height: 640px;
          width: 100%;
          box-shadow: rgb(0 0 0 / 30%) 0px 0px 12.5px,
            rgb(0 0 0 / 15%) 0px 0px 2.5px;
        }

        .center-modal .close-button {
          position: absolute;
          top: 10px;
          right: 10px;
          background: rgba(255, 255, 255, 0.5);
          border: none;
          z-index: 1;
          display: flex;
          justify-content: center;
          flex-direction: column;
          align-items: center;
          /* Consejo: Haz tu botón de cerrar relativamente grande para que sea fácil de hacer clic */
          min-width: 36px;
          min-height: 36px;
          border-radius: 50%;
        }

        .center-modal .headings {
          padding: 24px 24px 0 24px;
        }

        .center-modal h1 {
          margin: 32px 0 0 0;
          color: #222;
          text-decoration: none;
          font-family: Raleway;
          font-size: 24px;
          font-weight: 700;
          line-height: 28px;
          letter-spacing: 0px;
          text-align: left;
        }

        .center-modal h2 {
          font-family: Raleway;
          font-size: 16px;
          font-weight: 500;
          line-height: 24px;
          letter-spacing: 0px;
          text-align: left;
          color: #555;
          margin: 8px 0 0 0;
        }

        .center-modal .content {
          padding: 24px;
          display: flex;
          flex-direction: column;
        }

        .checkbox-group {
          display: flex;
          flex-direction: column;
          gap: 12px;
          margin: 16px 0;
        }

        .checkbox-item {
          display: flex;
          align-items: center;
          gap: 12px;
          padding: 8px;
          background: rgba(255, 255, 255, 0.3);
          border-radius: 6px;
        }

        .checkbox-item input[type="checkbox"] {
          width: 20px;
          height: 20px;
        }

        .checkbox-item label {
          font-family: "Nunito Sans", sans-serif;
          font-size: 14px;
          font-weight: 500;
          color: #333;
          cursor: pointer;
        }

        .submit-button {
          background: #ff6b35;
          color: white;
          border: none;
          padding: 12px 24px;
          border-radius: 6px;
          font-family: "Nunito Sans", sans-serif;
          font-size: 16px;
          font-weight: 700;
          cursor: pointer;
          margin-top: 16px;
          transition: background-color 0.2s;
        }

        .submit-button:hover {
          background: #e55a2b;
        }

        .submit-button:disabled {
          background: #ccc;
          cursor: not-allowed;
        }
      </style>
    </head>
    <body>
      <div class="center-modal">
        <!-- Botón cerrar -->
        <button class="close-button" onclick="OneSignalIamApi.close(event)">
          ✕
        </button>
        
        <div class="headings">
          <h1>¿Qué te gusta más?</h1>
          <h2>Cuéntanos tus preferencias para mejores recomendaciones</h2>
        </div>
        
        <div class="content">
          <div class="checkbox-group">
            <div class="checkbox-item">
              <input type="checkbox" id="option1" name="preferences" value="sports">
              <label for="option1">Deportes y Fitness</label>
            </div>
            <div class="checkbox-item">
              <input type="checkbox" id="option2" name="preferences" value="technology">
              <label for="option2">Tecnología y Gadgets</label>
            </div>
            <div class="checkbox-item">
              <input type="checkbox" id="option3" name="preferences" value="food">
              <label for="option3">Comida y Cocina</label>
            </div>
            <div class="checkbox-item">
              <input type="checkbox" id="option4" name="preferences" value="travel">
              <label for="option4">Viajes y Aventura</label>
            </div>
            <div class="checkbox-item">
              <input type="checkbox" id="option5" name="preferences" value="entertainment">
              <label for="option5">Entretenimiento y Juegos</label>
            </div>
          </div>
          
          <button class="submit-button" onclick="handleSurveyAnswer(event)">
            Enviar Respuestas
          </button>
        </div>
      </div>

      <script>
        function handleSurveyAnswer(e) {
          const checkboxes = document.querySelectorAll('input[name="preferences"]:checked');
          const selectedValues = Array.from(checkboxes).map(cb => cb.value);
          
          if (selectedValues.length === 0) {
            alert('Por favor selecciona al menos una opción');
            return;
          }

          // Opción 1: Enviar a tu endpoint backend
          const url = ""; // Reemplaza con tu URL de endpoint
          
          if (url) {
            fetch(url, {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                survey: 'preferences',
                answers: selectedValues,
                timestamp: new Date().toISOString()
              })
            }).then(response => {
              console.log('Respuestas de encuesta enviadas');
            }).catch(error => {
              console.error('Error enviando respuestas de encuesta:', error);
            });
          }
          
          // Opción 2: Usar etiquetas de OneSignal (sin backend requerido)
          // Descomenta las siguientes líneas para usar etiquetas:
          /*
          const tags = {};
          selectedValues.forEach(value => {
            tags[`preference_${value}`] = 'true';
          });
          OneSignalIamApi.sendTags(tags);
          */
          
          // Pasar selecciones mediante nombre de clic
          OneSignalIamApi.addClickName(e, selectedValues.join(','));
          
          // Cerrar mensaje
          OneSignalIamApi.close(e);
        }
      </script>
    </body>
  </html>
  ```
</Accordion>

***
