Aller au contenu principal
Mobile Guides

Guide complet sur les notifications push Expo 2026

Maîtrisez la configuration des notifications push Expo. Ce guide couvre les permissions, les tokens, l'envoi, la gestion et les bonnes pratiques de production pour une livraison fiable.

Guide complet sur les notifications push Expo 2026

Vous en êtes probablement au stade où l'app fonctionne, les utilisateurs sont connectés, et le produit demande désormais des flux de réengagement qui semblent natifs. Rappels de panier. Prompts d'avis. Alertes de nouveaux messages. Annonces de release. Le premier réflexe est souvent de « juste brancher les push », puis une semaine plus tard, vous déboguez pour comprendre pourquoi un appareil reçoit les alertes, pourquoi le simulateur semble bien s'enregistrer, et pourquoi personne n'arrive à expliquer pourquoi les clics n'ouvrent pas le bon écran.

C'est là que les notifications push Expo sont soit agréablement simples, soit étonnamment fragiles.

Expo offre aux équipes React Native une couche pratique au-dessus d'APNs et FCM, et c'est précisément pour cela que tant d'équipes l'utilisent. Mais l'écart entre une démo et une implémentation prête pour la production est bien réel. Le cycle de vie des tokens, le timing des permissions, la configuration des listeners, la conception des payloads et le nettoyage du backend comptent tous. Si vous déployez également des changements fréquents de logique applicative, le besoin de discipline opérationnelle s'accentue, surtout si votre travail de rétention dépend de la fiabilité de la messagerie et de la vélocité des releases. La livraison n'est utile que si l'expérience utilisateur qui l'entoure est prévisible.

Table of Contents

Les bases pour engager vos utilisateurs avec les Expo Push Notifications

Une Notifications push Expo sa configuration est séduisante pour une raison principale. Elle élimine une grande partie de la complexité liée à la messagerie native que les équipes ne souhaitent pas gérer dès le premier jour. Au lieu de construire d'abord toute l'infrastructure APNs et FCM, vous pouvez utiliser la gateway d'Expo et vous concentrer sur le comportement du produit, le routage, l'UX des permissions et la logique de messagerie backend.

Cette abstraction ne rend pas les notifications push « moins réelles ». Elle déplace simplement l'effort d'ingénierie.

Le service est également assez rapide pour que la performance ne soit généralement pas la première préoccupation. Du 14 mars 2023 au 12 juin 2023, l’API des notifications push d'Expo a affiché un temps de réponse médian de 42 millisecondes, une latence p99 de 273 millisecondes, et un taux d'erreur quotidien moyen de 0,17 % sur des dizaines de millions de messages quotidiens, according to l'analyse comparative du API d'Expo de Knock. Cela devrait rassurer toute équipe qui se demande si Expo est uniquement adapté aux prototypes.

Ce qu'Expo abstrait réellement

Quand les équipes parlent d'« Expo push », elles font souvent référence à plusieurs concepts distincts regroupés :

  • Routage du fournisseur : Expo transmet les messages à APNs pour iOS et FCM pour Android.
  • Format du token : Votre serveur stocke et envoie un Expo Push Token au lieu de gérer d'abord les tokens spécifiques à chaque plateforme.
  • Contrat de requête : Vous envoyez un payload par POST à l'API de push d'Expo plutôt que d'intégrer directement les API des providers natifs.

C'est pratique, mais cela crée aussi une confusion courante. Les équipes supposent parfois qu'Expo est responsable de chaque problème de livraison. En réalité, de nombreux échecs proviennent du code de l'app, de tokens obsolètes, de payloads malformés ou d'un mauvais flux de permissions.

Règle pratique : Considérez Expo comme une couche de transport fiable, et non comme un substitut à une conception client et backend solide.

Ce que signifie réellement la mise en production

Une démo fonctionnelle prouve seulement qu'un appareil a accepté un payload une seule fois. La mise en production, c'est autre chose :

Préoccupation Mentalité démo Mentalité production
Autorisations Poser la question Posez votre question, une fois la valeur utilisateur établie
Tokens Save once Rafraîchir, dédupliquer, expirer et réconcilier
Payloads Tout inclure data Garder des payloads légers et orientés action
Comportement de l'app Afficher une alerte Naviguer correctement et gérer l'état au premier plan
Opérations Tests manuels Accusés de réception, nettoyage, logs et gestion d'incidents

C'est toute la différence entre « envoyer des notifications » et « intégrer les notifications dans un vrai workflow produit ».

Configuration et mise en place initiale du projet

Beaucoup de problèmes avec les notifications Expo surviennent avant même le premier prompt de permission. Si la configuration de votre projet est négligée, le code client peut sembler correct alors que l'app se comporte de manière incohérente selon les builds.

Un ordinateur portable moderne sur un bureau en bois affichant des fichiers de configuration code pour la configuration d'un projet.

Commencez avec les bonnes librairies installées et un environnement de développement qui correspond à votre chemin de build. Si vous travaillez au-delà d'Expo Go, il est utile d'aligner votre workflow de release avec le guide de l'alternative Expo EAS de Capgo, car le comportement des notifications doit souvent être validé dans un build qui reflète plus fidèlement la production qu'un simple test en sandbox.

Installer les packages de notification

Au minimum, vous aurez généralement besoin de :

  • expo-notifications pour les demandes de permission, la récupération de token, les listeners et l'affichage des notifications.
  • expo-device car vous devriez sécuriser la récupération du token avec Device.isDevice.

Les commandes d'installation classiques dépendent de votre gestionnaire de packages, mais l'essentiel est l'alignement des versions avec votre SDK Expo. Ne mélangez pas des versions de packages arbitraires. Laissez Expo résoudre les versions compatibles.

Ajouter la configuration au niveau du projet

Gardez une config explicite. Un fichier minimal app.json ou app.config.js doit refléter le fait que les notifications font partie du contrat de votre app, pas d'un ajout tardif.

{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "plugins": ["expo-notifications"],
    "ios": {
      "bundleIdentifier": "com.example.myapp"
    },
    "android": {
      "package": "com.example.myapp"
    },
    "extra": {
      "eas": {
        "projectId": "your-project-id"
      }
    }
  }
}

Quelques détails sont importants ici :

  • Les bundle identifiers et noms de package doivent correspondre à l'app que vous déployez réellement.
  • Le plugin de notifications garantit que le projet natif reçoit la configuration requise lors du build.
  • L'EAS project ID est crucial quand la récupération du token nécessite que l'app soit associée au bon projet Expo.

Définir un gestionnaire de notifications tôt

A lot of basic tutorials wait too long to define notification behavior. Don’t. Put it near app startup so foreground behavior is predictable.

import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: true,
  }),
});

Les équipes décident si les notifications au premier plan doivent afficher une alerte, jouer un son ou modifier les badges. Le comportement exact dépend de votre produit. Une app de chat et une app de paiement ne feront pas les mêmes choix.

Si vous ne définissez pas intentionnellement le comportement au premier plan, votre équipe finira par débugger des notifications « manquantes » qui ont en réalité été reçues, mais jamais présentées comme le produit l'attendait.

Android nécessite une configuration de canal

En pratique, les canaux de notification Android ne sont pas optionnels. Si vous les ignorez, vos alertes peuvent paraître incohérentes ou ne pas répondre aux attentes des utilisateurs.

import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';

export async function configureAndroidNotifications() {
  if (Platform.OS !== 'android') return;

  await Notifications.setNotificationChannelAsync('default', {
    name: 'Default',
    importance: Notifications.AndroidImportance.MAX,
  });
}

Configurez cela lors de l'initialisation de l'application. Maintenez ensuite les ID des canaux stables. Les modifier sans précaution rendra le comportement des notifications difficile à analyser par la suite.

Demander la permission et capturer les tokens push

C'est la partie que beaucoup d'équipes copient depuis un snippet, pour le regretter plus tard.

Les demandes de permission nécessitent un timing précis, une connaissance de la plateforme et une gestion async rigoureuse. La capture du token doit se faire uniquement sur un appareil physique, seulement après la résolution des permissions, et seulement si vous êtes prêt à stocker le résultat sur votre backend immédiatement.

Un diagramme étape par étape montrant le processus d'obtention et de stockage des tokens de notification push Expo.

La fonction client qui devrait servir de base

Utilisez une fonction comme celle-ci comme point de départ :

import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';
import { Platform } from 'react-native';

type RegisterResult =
  | { ok: true; token: string }
  | { ok: false; reason: string };

export async function registerForExpoPushNotificationsAsync(): Promise<RegisterResult> {
  if (!Device.isDevice) {
    return { ok: false, reason: 'Push notifications require a physical device.' };
  }

  if (Platform.OS === 'android') {
    await Notifications.setNotificationChannelAsync('default', {
      name: 'Default',
      importance: Notifications.AndroidImportance.MAX,
    });
  }

  const permissions = await Notifications.getPermissionsAsync();
  let finalStatus = permissions.status;

  if (finalStatus !== 'granted') {
    const request = await Notifications.requestPermissionsAsync();
    finalStatus = request.status;
  }

  if (finalStatus !== 'granted') {
    return { ok: false, reason: 'Notification permission was not granted.' };
  }

  const projectId =
    Constants.expoConfig?.extra?.eas?.projectId ??
    Constants.easConfig?.projectId;

  if (!projectId) {
    return { ok: false, reason: 'Missing EAS project ID configuration.' };
  }

  const tokenResponse = await Notifications.getExpoPushTokenAsync({ projectId });

  return { ok: true, token: tokenResponse.data };
}

L'ordre est crucial. Vérifiez d'abord le type d'appareil, configurez le comportement du canal Android, résolvez les permissions, validez la configuration du projet, puis demandez le token Expo.

Pourquoi Device.isDevice n'est pas optionnel

C'est l'une des rares erreurs qui génère beaucoup de bruit tout en paraissant inoffensive. Les équipes expertes ne demandent la permission que de manière conditionnelle quand Device.isDevice est vrai, et un piège courant est d'omettre cette garde, ce qui amène les développeurs à envoyer des notifications à des tokens de simulateur invalides et à blâmer Expo alors que le problème vient de la configuration de l'app, comme décrit dans les notes d'implémentation des notifications Expo d'Eagerworks.

C'est pourquoi la vérification se trouve en haut de la fonction. Ne la cachez pas derrière un helper. Rendez-l’explicite.

Les résultats sur simulateur sont utiles pour les tests UI. Ils ne sont pas fiables pour valider l'enregistrement du token push.

Demander la permission au bon moment

Ne demandez pas sur l'écran de splash. Ne demandez pas avant que l'utilisateur ne comprenne la valeur ajoutée. Le meilleur moment est généralement après une action de l'utilisateur qui rend les bénéfices des notifications concrets, comme l'activation des mises à jour de livraison, la participation à une conversation ou l'enregistrement d'un article suivi.

Une bonne implémentation suit généralement ce flux :

  1. L'utilisateur atteint une étape clé d'une fonctionnalité.
  2. L'app explique l'intérêt des notifications dans votre propre UI.
  3. L'app demande l'autorisation système.
  4. Si l'autorisation est accordée, l'app stocke immédiatement le token sur le backend.

C'est à cette dernière étape que beaucoup d'apps échouent. Elles récupèrent le token, le loguent localement et repoussent l'enregistrement côté backend. Plus tard, le support ne peut pas savoir quel appareil avait quel token à quel moment.

Voici un exemple simple de stockage du token après l'enregistrement :

export async function enablePushForCurrentUser(userId: string) {
  const result = await registerForExpoPushNotificationsAsync();

  if (!result.ok) {
    return result;
  }

  await fetch('https://api.example.com/push-tokens', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer user-session-token',
    },
    body: JSON.stringify({
      userId,
      token: result.token,
      platform: Platform.OS,
    }),
  });

  return result;
}

Plus loin dans le workflow, ce guide sert de référence visuelle :

Pour les équipes qui publient de nombreuses releases, il est utile de considérer l'enregistrement du token comme faisant partie de l'état opérationnel de l'app, et pas seulement de l'onboarding. Cette approche s'accorde bien avec les workflows de livraison d'apps Expo, où le comportement de l'app peut changer fréquemment et où l'état du backend doit rester synchronisé.

Envoyer des notifications depuis votre serveur

Une fois que votre backend possède un Expo Push Token valide, l'envoi d'une notification est simple. La difficulté ne réside pas dans la requête elle-même, mais dans ce qui doit figurer dans le payload et dans la confiance accordée à l'état côté client.

Voici un exemple minimaliste de style Node utilisant fetch:

type ExpoPushMessage = {
  to: string;
  title: string;
  body: string;
  sound?: 'default' | null;
  data?: Record<string, unknown>;
};

export async function sendExpoPushNotification(token: string) {
  const message: ExpoPushMessage = {
    to: token,
    title: 'New review received',
    body: 'Tap to open the order details.',
    sound: 'default',
    data: {
      type: 'new_review',
      orderId: 'ord_123',
      screen: 'OrderDetails',
    },
  };

  const response = await fetch('https://exp.host/--/api/v2/push/send', {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Accept-encoding': 'gzip, deflate',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(message),
  });

  const result = await response.json();
  return result;
}

Rôle de chaque champ du payload

Ne traitez pas le payload comme un fourre-tout. Chaque champ doit avoir un but précis.

Champ Finalité Conseils pratiques
to Cibler le token de push Expo Valider qu'il appartient bien à l'enregistrement de l'appareil actuel
title Titre de la notification Restez court et lisible pour l'utilisateur
body Texte principal visible Rendre l'action claire
sound Comportement du son système Use sparingly for high-value alerts
data Métadonnées spécifiques à l'app Privilégiez les IDs et les indices de route au contenu riche

Le data l'objet est l'endroit où les workflows produit deviennent utiles. Vous pouvez passer un type et un ID d'enregistrement, puis laisser l'app récupérer les dernières données lorsque l'utilisateur tape dessus. C'est plus sûr que d'intégrer des blobs volumineux ou sensibles directement dans le payload.

Gardez des payloads légers et simples

According to le guide de Courier sur les notifications Expo, les Expo Push Tokens doivent être traités comme éphémères ; les payloads dépassant les limites de taille d'environ 4 Ko peuvent être rejetés. Un pattern fiable consiste à envoyer de petits payloads de métadonnées tels que { "type": "new_review", "id": 123 } plutôt que de gros JSON ou des médias intégrés. Ce conseil colle à ce qui fonctionne dans les systèmes réels. Les payloads légers échouent moins souvent et vieillissent mieux quand la logique de l'app change.

Envoyez assez de données pour orienter l'utilisateur. Récupérez le reste une fois l'app ouverte.

Bonnes pratiques côté serveur

Une fonction d'envoi basique suffit pour les tests. En production, elle assume généralement quelques responsabilités de plus :

  • Persister les tentatives d'envoi : Enregistrer l'intention de notification avec l'ID utilisateur, le token, le type de payload et l'horodatage.
  • Séparer la génération de contenu du transport : Générer le texte du message dans une couche et la requête Expo API dans une autre.
  • Gérer les retours d'invalidation : Si Expo signale plus tard DeviceNotRegistered, marquez ce token comme obsolète et arrêtez de réessayer aveuglément.
  • Utiliser un design compatible avec les webhooks : Si votre système émet déjà des événements, routez les déclencheurs de notification via le même type de modèle de traitement de webhook backend que vous utilisez ailleurs.

Avant de déboguer les listeners côté client, envoyez d'abord une notification push de test manuelle. Si un token reçoit une notification simple avec un petit payload, votre chemin de transport est probablement opérationnel. Sinon, ne commencez pas par modifier la navigation code. Commencez par valider le token, la structure du payload et l'état des permissions.

Gérer les notifications entrantes dans votre application

La livraison n'est que la moitié de la fonctionnalité. L'application doit effectuer une action cohérente à la réception de la notification et lorsque l'utilisateur appuie dessus.

Cela signifie qu'il faut gérer deux moments distincts :

  • la notification arrive alors que l'application est ouverte
  • l'utilisateur interagit avec la notification depuis le volet système ou l'écran de verrouillage

Un diagramme illustrant le cycle de vie des notifications push pour les applications mobiles en premier plan et en arrière-plan.

Réception au premier plan et réponse utilisateur : deux événements distincts

Une configuration fiable inclut généralement les deux listeners :

import { useEffect } from 'react';
import * as Notifications from 'expo-notifications';

export function useNotificationObservers(
  onForegroundMessage: (notification: Notifications.Notification) => void,
  onNotificationTap: (response: Notifications.NotificationResponse) => void
) {
  useEffect(() => {
    const receivedSub = Notifications.addNotificationReceivedListener(
      (notification) => {
        onForegroundMessage(notification);
      }
    );

    const responseSub = Notifications.addNotificationResponseReceivedListener(
      (response) => {
        onNotificationTap(response);
      }
    );

    return () => {
      receivedSub.remove();
      responseSub.remove();
    };
  }, [onForegroundMessage, onNotificationTap]);
}

addNotificationReceivedListener s'exécute quand l'app est active. addNotificationResponseReceivedListener s'exécute quand l'utilisateur appuie sur une notification reçue. Ne les confondez pas : elles servent des parcours UX différents.

Lire le payload de données et naviguer de manière intentionnelle

Voici un pattern pratique pour gérer le tap :

type NotificationData = {
  type?: string;
  orderId?: string;
  screen?: string;
};

export function handleNotificationTap(
  response: Notifications.NotificationResponse,
  navigation: any
) {
  const data =
    response.notification.request.content.data as NotificationData;

  if (data.screen === 'OrderDetails' && data.orderId) {
    navigation.navigate('OrderDetails', { orderId: data.orderId });
    return;
  }

  if (data.type === 'new_review') {
    navigation.navigate('Inbox');
    return;
  }

  navigation.navigate('Home');
}

Ce pattern reste résilient car le payload contient des indices de routage, pas des documents entiers. Si l'ordre a changé depuis l'envoi de la notification, l'app peut récupérer l'état actuel du serveur après la navigation.

Une notification sur laquelle on appuie doit mener à une destination évidente. Si votre chemin de repli est flou, les utilisateurs le remarqueront immédiatement.

Comportement au premier plan : suivre le contexte utilisateur

Quand l'app est déjà ouverte, afficher aveuglément une alerte de type système peut sembler maladroit. Parfois, la meilleure approche est une bannière in-app, une mise à jour de badge ou un refresh silencieux. Un écran de boîte de réception de support n'a peut-être pas besoin d'une alerte visible si l'utilisateur est déjà en train de lire cette conversation.

C'est pourquoi votre listener de foreground devrait se diviser par route et par type de notification. Par exemple :

  • Écran de chat ouvert : ajouter le message et éviter une bannière redondante
  • Dashboard ouvert : afficher un toast léger dans l'app
  • Événement de compte critique : utiliser un composant UI plus marqué

Une approche simple ressemble à ceci :

export function handleForegroundNotification(
  notification: Notifications.Notification,
  currentRouteName: string
) {
  const data = notification.request.content.data as { type?: string };

  if (currentRouteName === 'ChatThread' && data.type === 'new_message') {
    // refresh local thread state
    return;
  }

  // otherwise show your own in-app UI or update badges
}

Si votre app ne distingue pas ces contextes, les utilisateurs ressentiront plus vite une fatigue liée aux notifications, même si la livraison est techniquement correcte.

Bonnes pratiques en production et pièges courants

La plupart des configurations de notifications push Expo défaillantes ne sont pas dues aux limites d'Expo. Elles échouent parce que les équipes supposent que le token est permanent, que les payloads peuvent tout contenir et que les mises à jour de l'app n'affecteront pas la logique de notification.

Cette supposition ne survit pas en production.

Une infographie sous forme de checklist présentant huit bonnes pratiques pour gérer les notifications push de production pour les applications mobiles.

Les tokens sont éphémères, pas des identifiants

Un Expo Push Token doit être traité comme un bail temporaire, et non comme un identifiant d'appareil permanent. Les tokens peuvent changer après une réinstallation, un changement d'OS ou d'autres événements de cycle de vie. Si un token finit par revenir DeviceNotRegistered, votre backend doit cesser de le considérer comme actif.

Un modèle backend pratique stocke :

  • ID utilisateur
  • la plateforme
  • les métadonnées liées à l'installation
  • le token actuel
  • l'horodatage de dernière présence
  • le statut (actif, obsolète ou révoqué)

Ne vous contentez pas de stocker un champ token dans la table utilisateur. Les utilisateurs possèdent plusieurs appareils et l'état des appareils change.

Refresh strategy matters more than most tutorials admit

Les guides officiels de l'écosystème laissent un réel vide opérationnel ici. Le contenu existant sur les notifications push Expo n'explique souvent pas comment maintenir la validité des tokens à travers Cycles de révision de l'App Store et mises à jour OTA, ce qui est essentiel pour les équipes qui déploient des changements en direct, car la fiabilité des push dépend de l'état actuel du token et de la synchronisation backend, comme indiqué dans Documentation des notifications Expo.

Cela influence la conception de vos déclencheurs de rafraîchissement. Les moments idéaux pour réconcilier l'état du token incluent :

  • Lancement de l'app après une mise à jour
  • Connexion de l'utilisateur
  • Changement des paramètres de permission
  • Rotation des credentials lors de votre processus de release
  • Flux de récupération après des tickets de support liés aux push

La sécurité et la conformité n'ont pas leur place en fin de sprint

Beaucoup de tutoriels Expo se concentrent sur la mécanique et ignorent les risques opérationnels. C'est acceptable pour des apps de loisir, mais pas pour des produits de la fintech, du commerce réglementé ou de la santé.

L'analyse de Courier sur les lacunes des notifications Expo pour l'entreprise met en évidence un manque de conseils pratiques concernant l'enregistrement du consentement, les pistes d'audit et la minimisation de l'exposition des données sensibles. L'enseignement technique est simple :

  • Ne placez pas de données métier sensibles dans le texte ou les métadonnées du payload des notifications.
  • Journalisez les changements de consentement côté serveur.
  • Enregistrez quelle intention de notification a été envoyée à quel token.
  • Utilisez des IDs dans les payloads et récupérez le contenu protégé après l'ouverture de l'app.

For teams aligning release operations with broader conformité à l'App Store et pratiques de sécurité API, le push doit être soumis à la même rigueur de revue que l'auth, l'analytics et les logs d'événements backend.

Les notifications push sont des messages destinés aux utilisateurs, mais elles posent aussi un problème de systèmes distribués. Traitez-les avec le même soin que l'état d'auth et les événements de paiement.

Ce qui fonctionne généralement et ce qui casse habituellement

Fonctionne généralement Échoue généralement
Demander la permission après avoir clairement expliqué la valeur ajoutée Afficher le prompt dès le premier frame
Tester sur des appareils réels Se fier à l'enregistrement des simulateurs
Stocker les tokens avec le contexte de l'appareil Un seul token par enregistrement utilisateur
Envoyer de petits payloads de métadonnées Intégrer des blobs volumineux ou sensibles
Gérer séparément les événements au premier plan et au clic Supposer que toutes les notifications suivent un seul chemin
Expirer les tokens obsolètes de manière agressive Réessayer indéfiniment avec des tokens invalides

Une configuration Expo Push solide n'est pas compliquée. Elle demande de la discipline.


Si votre équipe déploie des changements fréquents de logique applicative et nécessite un contrôl’accru sur le comportement des releases, les rollbacks et la visibilité des livraisons, Capgo vaut le détour. Cela aide les équipes mobiles à déployer des mises à jour rapidement sans attendre la validation des stores, ce qui est particulièrement utile lorsque les flux de notifications, la logique de routage ou les correctifs côté client doivent atteindre les utilisateurs rapidement.

Live updates pour les apps Capacitor

Quand un bug de la couche web est en production, déployez le correctif via Capgo au lieu d'attendre des jours l'approbation des stores. Les utilisateurs reçoivent la mise à jour en arrière-plan, tandis que les changements natifs suivent le circuit de validation habituel.

Les derniers articles du blog

Capgo vous apporte les meilleures informations pour créer une application mobile vraiment professionnelle.