Cómo implementar notificaciones push en el app móvil de tu servidor de MU Online
Implementa notificaciones push reales en el app móvil o PWA de tu servidor de MU Online, cubriendo Firebase Cloud Messaging, segmentación por evento de juego, integración con el GameServer y buenas prácticas para evitar la cancelación de permisos.
Las notificaciones push transforman el portal o app de tu servidor de MU Online en un canal de comunicación en tiempo real, capaz de avisar al jugador sobre el inicio de un Castle Siege, la apertura de un evento raro o una promoción relámpago en la tienda — incluso con el navegador o app cerrado. A
Las notificaciones push transforman el portal o app de tu servidor de MU Online en un canal de comunicación en tiempo real, capaz de avisar al jugador sobre el inicio de un Castle Siege, la apertura de un evento raro o una promoción relámpago en la tienda — incluso con el navegador o app cerrado. A diferencia del correo o Discord, el push llega instantáneamente a la pantalla del dispositivo, con una tasa de atención mucho más alta. Implementar esto correctamente exige integrar Firebase Cloud Messaging, configurar un Service Worker en el PWA, conectar eventos reales del servidor de juego a disparadores de envío, y sobre todo respetar la preferencia del jugador para no generar cancelación masiva del permiso. Este tutorial cubre la implementación completa, desde cero hasta la integración con eventos del GameServer.
Por qué push notification y no solo correo o Discord
Cada canal de comunicación tiene un papel distinto en la retención de jugadores. El correo es asíncrono y bueno para contenido más largo (patch notes, resúmenes semanales); Discord depende de que el jugador tenga las notificaciones activas en ese servidor específico; el push llega directo a la pantalla de bloqueo del celular o como notificación del sistema operativo, con un tiempo de reacción mucho más rápido. Para avisos sensibles al tiempo — "El Castle Siege empieza en 10 minutos", "Invasion de Kundun activa ahora" — el push es el único canal con posibilidades reales de que el jugador lo vea a tiempo para actuar.
Eligiendo entre PWA y app nativo
Antes de implementar el push, define la plataforma. Para la mayoría de los servidores de MU Online, un PWA bien configurado es la opción más eficiente:
| Criterio | PWA (sitio instalable) | App nativo (Android/iOS) |
|---|---|---|
| Costo de desarrollo | Bajo (reaprovecha el sitio existente) | Alto (codebase separado) |
| Publicación en tienda | No necesaria | Exige cuenta de desarrollador y aprobación |
| Soporte a push en Android | Completo | Completo |
| Soporte a push en iOS | Parcial (Safari 16.4+, requiere instalación en pantalla de inicio) | Completo |
| Mantenimiento | Una única base de código | Dos bases de código (o framework híbrido) |
Para la mayoría de los casos, empieza con PWA y solo evalúa un app nativo si la base de jugadores en iOS es lo suficientemente grande para justificar el costo adicional.
Configurando Firebase Cloud Messaging
Firebase Cloud Messaging (FCM) es el servicio de envío más usado por ser gratuito y cubrir Android, iOS y Web. Los pasos iniciales de configuración:
- Crear un proyecto en la consola de Firebase (console.firebase.google.com).
- Agregar un app Web al proyecto y copiar las credenciales (
apiKey,projectId,messagingSenderId, etc.). - Generar un par de claves VAPID en la pestaña de Cloud Messaging, necesario para Web Push.
- Instalar el SDK en el proyecto del sitio (
npm install firebase).
Ejemplo de configuración inicial en un proyecto Next.js:
// lib/firebase.js
import { initializeApp } from 'firebase/app';
import { getMessaging, getToken, onMessage } from 'firebase/messaging';
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
const app = initializeApp(firebaseConfig);
export const messaging = typeof window !== 'undefined' ? getMessaging(app) : null;
Registrando el Service Worker
El push solo funciona con un Service Worker registrado, responsable de recibir la notificación incluso con la pestaña/app cerrada:
// public/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: 'SUA_API_KEY',
projectId: 'SEU_PROJECT_ID',
messagingSenderId: 'SEU_SENDER_ID',
appId: 'SEU_APP_ID',
});
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
self.registration.showNotification(payload.notification.title, {
body: payload.notification.body,
icon: '/icons/icon-192.png',
});
});
Este archivo debe quedar en la raíz pública del sitio (public/firebase-messaging-sw.js), accesible directamente por URL, para que el navegador pueda registrarlo.
Solicitando el permiso del jugador correctamente
Pedir permiso de notificación tan pronto el jugador entra al sitio por primera vez es el error más común y la principal causa de rechazo. El enfoque correcto es contextual:
- Espera a que el jugador realice una acción relevante (ej.: registrarse, visitar la página de eventos) antes de pedir el permiso.
- Explica el valor antes del prompt nativo del navegador: un pequeño banner "¿Quieres que te avisemos cuando empiece el Castle Siege? Activa las notificaciones" antes de llamar a la API real de permiso.
- Nunca pidas de nuevo de forma insistente si el jugador lo niega — respeta su elección y ofrece la opción de activarlo después en la configuración del perfil.
async function solicitarPermissao() {
const permissao = await Notification.requestPermission();
if (permissao === 'granted') {
const token = await getToken(messaging, { vapidKey: 'SUA_VAPID_KEY' });
// enviar token para o backend, associado ao jogador logado
await fetch('/api/push/registrar', {
method: 'POST',
body: JSON.stringify({ token }),
});
}
}
Segmentando notificaciones por tipo de evento
Igual que en la newsletter, notificar todo a todo el mundo genera cansancio y cancelación de permiso. Estructura categorías que el jugador pueda elegir:
| Categoría | Ejemplo de contenido | Frecuencia típica |
|---|---|---|
| Eventos PvP | Inicio de Castle Siege, guerra de guild | 1-2x por semana |
| Eventos PvE de servidor | Invasion, Golden Invasion, Chaos Castle especial | Diaria, en horarios fijos |
| Tienda y promociones | Descuento relámpago, nuevo paquete de créditos | Esporádica |
| Mantenimiento/infra | Aviso de caída programada, actualización de patch | Solo cuando sea necesario |
Guarda la preferencia de cada jugador (qué categorías aceptó) en una tabla de la base de datos del sitio, vinculada al token de push, y siempre segmenta el envío por esa preferencia.
Integrando eventos reales del GameServer al envío
La parte más poderosa (y más laboriosa) es conectar el propio GameServer al sistema de push, para notificar el momento exacto en que un evento de juego comienza, no un horario fijo aproximado. Una arquitectura común:
- Un pequeño servicio intermediario monitorea los logs del GameServer o consulta la base de datos del juego periódicamente (cada 10-30 segundos), buscando el cambio de estado de eventos (ej.: columna
EventStatusen la tabla de configuración de evento). - Al detectar que un evento pasó de "cerrado" a "abierto", ese servicio llama a la API del backend del sitio.
- El backend del sitio consulta la tabla de tokens de push segmentados por la categoría correspondiente y envía la notificación vía API de Firebase Admin SDK.
Ejemplo simplificado del envío en el backend, usando Firebase Admin:
// server: dispara notificação quando o serviço detecta evento aberto
const admin = require('firebase-admin');
async function notificarEvento(categoria, titulo, corpo) {
const tokens = await buscarTokensPorCategoria(categoria); // consulta ao banco
await admin.messaging().sendEachForMulticast({
tokens,
notification: { title: titulo, body: corpo },
});
}
// exemplo de chamada quando o serviço detecta Devil Square aberto
notificarEvento('eventos_pve', 'Devil Square está aberto!', 'Corra para participar antes que feche.');
Probando en distintas plataformas
Antes de lanzar a todos los jugadores, prueba el flujo completo en cada entorno objetivo:
- Android (Chrome): soporte completo, prueba con el app/PWA en segundo plano y totalmente cerrado.
- iOS (Safari): exige que el jugador haya instalado el PWA en la pantalla de inicio (Agregar a la Pantalla de Inicio); el push no funciona solo con el navegador abierto normalmente.
- Escritorio (Chrome/Edge/Firefox): soporte completo, útil para jugadores que siguen desde la computadora.
Documenta las limitaciones de iOS claramente para los jugadores en el propio sitio, evitando tickets de soporte de quienes no lograron activarlo por no haber instalado el PWA correctamente.
Errores comunes y soluciones
| Síntoma | Causa probable | Solución |
|---|---|---|
| Permiso rechazado por la mayoría de los jugadores | Solicitud de permiso demasiado temprana/agresiva | Usar un banner contextual antes del prompt nativo |
| Las notificaciones no llegan en iOS | PWA no instalado en la pantalla de inicio | Orientar la instalación manual, limitación de Safari |
| El Service Worker no se registra | Archivo fuera de la raíz pública o ruta incorrecta | Confirmar que public/firebase-messaging-sw.js sea accesible vía URL |
| Muchos jugadores desactivan las notificaciones tras poco tiempo | Envío genérico sin segmentación | Implementar categorías y respetar la preferencia del jugador |
| La notificación de evento llega atrasada | Polling del servicio intermediario con intervalo demasiado largo | Reducir el intervalo de chequeo o usar un trigger directo en la base de datos |
Lista de verificación de notificaciones push
- Decisión tomada entre PWA y app nativo, según la base de jugadores.
- Proyecto Firebase configurado con claves VAPID generadas.
- Service Worker registrado y accesible en la raíz pública del sitio.
- Flujo de solicitud de permiso contextual implementado.
- Categorías de notificación definidas y preferencias guardadas por jugador.
- Integración entre eventos reales del GameServer y el envío de push.
- Pruebas realizadas en Android, iOS (PWA instalado) y escritorio.
Con el push funcionando de punta a punta, el servidor gana un canal de comunicación en tiempo real que complementa el correo y Discord — vale la pena revisar el tutorial de cómo crear un servidor de MU Online para garantizar que la infraestructura de backend soporte esta integración con el GameServer sin cuellos de botella de rendimiento.
Preguntas frecuentes
¿Necesito un app nativo o basta con solo el sitio (PWA)?
Un PWA (Progressive Web App) bien configurado ya soporta push notifications tanto en Android como, con limitaciones, en iOS a partir de versiones recientes de Safari. Para la mayoría de los servidores de MU Online, un PWA es suficiente y mucho más barato de mantener que un app nativo publicado en las tiendas.
¿Qué servicio usar para enviar las notificaciones push?
Firebase Cloud Messaging (FCM) de Google es el estándar del mercado, gratuito para prácticamente cualquier volumen de un servidor de MU Online, y funciona tanto para apps nativos Android/iOS como para PWAs vía Web Push.
¿Cómo evito que los jugadores desactiven las notificaciones por exceso de envíos?
Segmenta por tipo de evento y permite que el jugador elija qué categorías quiere recibir (Castle Siege, invasiones, promociones de la tienda). Las notificaciones genéricas y excesivas son la principal causa de desactivación masiva del permiso.
¿Es posible notificar al jugador en tiempo real cuando empieza un evento de juego (ej.: se abrió Devil Square)?
Sí, integrando el GameServer (o un servicio intermediario que lee logs/eventos del servidor) a un webhook que dispara la notificación push en cuanto inicia el evento. Esto requiere un pequeño servicio de integración entre el emulador y Firebase.
¿Las notificaciones push funcionan con el navegador cerrado?
Sí, ese es justamente el diferencial del push frente a las notificaciones in-app comunes. Un Service Worker registrado en el navegador o dispositivo recibe la notificación incluso con el sitio/app cerrado, siempre que el usuario haya concedido el permiso anteriormente.