Aller au contenu principal
Mobile Guides

Guide complet des notifications push Expo 2026

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

Guide complet des notifications push Expo 2026

Vous êtes probablement à l’étape 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. Invitations à laisser un avis. Alertes de nouveaux messages. Annonces de release. Le premier réflexe est souvent de « brancher les push », puis une semaine plus tard, vous déboguez pourquoi un seul appareil reçoit des alertes, le simulateur semble s’enregistrer correctement, et personne ne sait pourquoi les taps 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 de FCM, ce qui explique pourquoi tant d’équipes l’utilisent. Mais l’écart entre une démo et une implémentation prête pour la production est 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 aussi fréquemment des changements de logique applicative, le besoin de discipline opérationnelle devient encore plus aigu, surtout si votre travail de rétention dépend d’un messaging fiable et d’une vélocité de release. La livraison n’est utile que si l’expérience utilisateur qui l’entoure est prévisible.

Table des matières

Les fondamentaux pour engager vos utilisateurs avec les notifications push Expo

Une Notification push Expo sa configuration séduit pour une raison avant tout. Elle élimine une grande partie de la complexité de messagerie native que les équipes ne veulent pas gérer dès le départ. Au lieu de mettre en place d'abord l'intégration directe APNs et FCM, vous pouvez passer par la passerelle 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 push « moins réelles ». Elle change simplement l’endroit où vous concentrez vos efforts 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 de notifications push d'Expo a affiché un temps de réponse médian de 42 millisecondes, une latence p99 de 273 millisecondes, et un un taux d'erreur quotidien moyen de 0,17 % sur des dizaines de millions de messages quotidiens, selon les l'analyse comparative de Knock sur l’API push d'Expo. Cela devrait rassurer toute équipe qui se demande si Expo ne convient qu'aux prototypes.

Ce qu'Expo abstrait réellement

Quand les équipes parlent de « push Expo », 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 en POST vers l’API push d’Expo plutôt que d’intégrer directement les API des fournisseurs natifs.

C’est utile, mais cela crée aussi un malentendu courant. Les équipes pensent parfois qu’Expo gère tous les problèmes de livraison. En pratique, beaucoup d’échecs viennent de l’code de l’app, de tokens obsolètes, de payloads mal formés ou d’un flux de permissions mal conçu.

Règle pratique : Considérez Expo comme une couche de transport fiable, pas comme un substitut à une bonne conception côté client et backend.

Ce que signifie vraiment « prêt pour la production »

Une démo fonctionnelle ne prouve qu’un seul appareil a accepté un seul payload une seule fois. La production, c’est autre chose :

Enjeu Esprit démo Esprit production
Autorisations Demander à l’IA Demander dans le contexte, une fois la valeur claire
Tokens Save once Rafraîchir, dédupliquer, expirer et réconcilier
Payloads Tout mettre dans le payload data Garder des payloads légers et axés sur l'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 la différence entre « envoyer des notifications » et « intégrer les notifications à un vrai workflow produit ».

Mise en place et configuration initiales du projet

Beaucoup de problèmes avec les notifications push Expo commencent avant le premier prompt d’autorisation. Si la configuration de votre projet est approximative, le client code peut sembler correct, mais l’application reste incohérente d’un build à l’autre.

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

Commencez par installer les bonnes bibliothèques 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 Capgo pour remplacer Expo EAS, car le comportement des notifications doit souvent être validé dans un build qui reflète la production plus fidèlement qu’une simple exécution en sandbox.

Installer les packages de notification

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

  • expo-notifications pour les demandes d’autorisation, la récupération des tokens, les listeners et l’affichage des notifications.
  • expo-device car vous devez protéger la récupération des tokens avec Device.isDevice.

Les commandes d’installation typiques dépendent de votre gestionnaire de paquets, mais l’essentiel est d’aligner les versions avec votre Expo SDK. Ne mélangez pas des versions de paquets arbitraires. Laissez Expo résoudre les versions compatibles.

Ajouter la configuration au niveau du projet

Gardez votre config explicite. Une config minimale app.json ou app.config.js doit refléter le fait que les notifications font partie intégrante du contrat de votre app, et non 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 :

  • Identifiants de bundle 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'ID de projet EAS est crucial lorsque la récupération de votre token nécessite que l'app soit associée au bon projet Expo.

Définir un gestionnaire de notification dès le début

Beaucoup de tutoriels de base tardent à définir le comportement des notifications. Ne faites pas la même chose. Placez cette configuration au démarrage de l’app pour un comportement en premier plan prévisible.

import * as Notifications from 'expo-notifications';

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

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

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

Android nécessite une configuration de canal

Les canaux de notification Android ne sont pas optionnels en pratique. Si vous les ignorez, vos alertes peuvent sembler incohérentes ou ne pas correspondre 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-le lors de l’initialisation de l’app. Gardez ensuite les IDs de canal stables. Les modifier à la légère complique la compréhension du comportement des notifications plus tard.

Demander la permission et capturer les tokens push

C’est la partie que beaucoup d’équipes copient depuis un extrait de code, puis finissent par regretter.

Les demandes d’autorisation exigent un bon timing, une prise en compte de la plateforme et une gestion asynchrone rigoureuse. La capture du token ne doit se faire que sur un appareil physique, uniquement après la résolution des autorisations, et seulement si vous êtes prêt à stocker le résultat sur votre backend immédiatement.

Un schéma étape par étape montrant le processus d’obtention et de stockage des tokens de notification push Expo.

La fonction client qui doit 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 compte. Vous vérifiez d’abord le type d’appareil, définissez 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 semblant inoffensive. Les équipes expertes ne demandent l’autorisation que conditionnellement, lorsque Device.isDevice est vrai, et un piège courant consiste à sauter cette garde, ce qui pousse les développeurs à envoyer des notifications vers des tokens de simulateur invalides et à blâmer Expo, alors que le problème vient réellement de la configuration de l’app, comme décrit dans les notes d’implémentation des notifications Expo d’Eagerworks.

C’est pourquoi le contrôle se trouve en haut de la fonction. Ne le cachez pas derrière un helper. Rendez-l’évident.

Les résultats du simulateur sont utiles pour tester l’interface. Ils ne sont pas fiables pour valider l’enregistrement du token push.

Demander la permission au bon moment

Ne demandez pas dès l’écran de démarrage. Ne demandez pas avant que l’utilisateur ne comprenne la valeur. Le meilleur moment est généralement après une action utilisateur qui rend concrets les avantages des notifications, comme activer les mises à jour de livraison, rejoindre une conversation ou enregistrer un élément suivi.

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

  1. L’utilisateur atteint un point clé de la fonctionnalité.
  2. L’application explique la valeur des notifications dans votre propre interface.
  3. L’application demande l’autorisation système.
  4. L’application stocke le token sur le backend immédiatement si l’autorisation est accordée.

C’est à cette dernière étape que beaucoup d’applications échouent. Elles récupèrent le token, le loguent en local et reportent l’enregistrement sur le 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 tard dans le workflow, ce tutoriel sert de référence visuelle utile :

Pour les équipes qui développent des apps avec de nombreuses releases, il est aussi utile de considérer l’enregistrement des tokens comme faisant partie de l’état opérationnel de l’app, et pas seulement de l’onboarding. Cette approche s’inscrit bien dans une vision plus large Workflows de livraison d’applications Expo, où le comportement de l’application peut changer fréquemment et où l’état du backend doit rester synchronisé.

Envoyer des notifications depuis votre serveur

Une fois que votre backend dispose d’un Expo Push Token valide, l’envoi d’une notification est simple. Le plus difficile n’est pas la requête elle-même, mais de décider ce qui doit figurer dans le payload et quelle confiance accorder à l’état côté client.

Voici un exemple minimaliste de type 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;
}

Le rôle de chaque champ du payload

Ne traitez pas le payload comme un fourre-tout. Chaque champ doit avoir sa raison d’être.

Champ Objectif Conseils pratiques
to Expo Push Token cible Valider qu’il appartient à l’enregistrement de l’appareil actuel
title Titre de la notification Gardez-le court et lisible
body Texte principal visible Rendez l’action claire
sound Comportement du son système À réserver aux alertes à forte valeur
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 appuie. C'est plus sûr que d'intégrer des blobs volumineux ou sensibles directement dans le payload.

Gardez les payloads petits et sans surprise

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 perdus. 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 inline. Ce conseil correspond à ce qui fonctionne dans les systèmes réels. Les petits payloads échouent moins souvent et vieillissent mieux lorsque la logique de l’application évolue.

Envoyez assez de données pour router l’utilisateur. Récupérez le reste une fois l’application ouverte.

Bonnes pratiques côté serveur

Une fonction d’envoi basique suffit pour les tests. En production, elle ajoute généralement quelques responsabilités supplémentaires :

  • Persister les tentatives d’envoi : Enregistrez l’intention de notification avec l’ID utilisateur, le token, le type de payload et l’horodatage.
  • Séparer la génération du contenu de la transmission : Composez le contenu du message dans une couche et la requête Expo API dans une autre.
  • Gérez le retour d’invalidation : Si Expo signale ensuite DeviceNotRegistered, marquez ce token comme obsolète et arrêtez de réessayer à l’aveugle.
  • Adoptez une architecture compatible webhook : 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 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 lorsque la notification arrive 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 centre de notifications ou l'écran de verrouillage

Un diagramme de flux illustrant le cycle de vie des notifications push pour les applications mobiles en modes foreground et background.

Réception au premier plan et réponse utilisateur sont des é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 lorsque l’application est active. addNotificationResponseReceivedListener s’exécute quand l’utilisateur appuie sur une notification reçue. Ne les mélangez pas mentalement : elles répondent à des parcours UX différents.

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

Voici un modèle pratique pour gérer les appuis :

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 modèle reste robuste car le payload contient des indices de routage, et non des documents entiers. Si la commande a changé depuis l’envoi de la notification, l’application peut récupérer l’état actuel du serveur après la navigation.

Une notification tapée doit mener à une destination unique et évidente. Si votre parcours de repli est flou, les utilisateurs le remarquent immédiatement.

Comportement au premier plan adapté au contexte utilisateur

Lorsque l’app est déjà ouverte, afficher aveuglément une alerte de type système peut paraître maladroit. Parfois, la bonne approche est un bandeau in-app, une mise à jour du badge ou un rafraîchissement silencieux. Un écran de boîte de réception du support n’a peut-être pas besoin d’une alerte visible si l’utilisateur lit déjà cette conversation.

C’est pourquoi votre listener au premier plan doit brancher selon la route et le type de notification. Par exemple :

  • Écran de chat ouvert : ajouter le message et éviter un bandeau redondant
  • Dashboard ouvert : afficher un toast in-app léger
  • Événement critique du compte : afficher un traitement 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 la fatigue des notifications plus vite, même si la livraison est techniquement correcte.

Bonnes pratiques en production et pièges courants

La plupart des configurations de notification push Expo cassées ne échouent pas parce qu’Expo est trop limité. Elles échouent parce que les équipes supposent que le token est permanent, que les payloads peuvent contenir n’importe quoi et que les mises à jour de l’app n’affecteront pas la logique de notification.

Cette hypothèse ne tient pas en production.

Infographie checklist : huit bonnes pratiques pour gérer les notifications push en production pour les applis mobiles.

Les tokens sont éphémères, pas des enregistrements d'identité

Il vaut mieux traiter un Expo Push Token comme un bail, pas comme un identifiant d’appareil à vie. Les tokens peuvent être renouvelés après une réinstallation, un changement d’OS ou d’autres événements du cycle de vie. Si un token finit par réapparaître DeviceNotRegistered, votre backend ne doit plus le considérer comme actif.

Un modèle backend concret stocke :

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

Ne vous contentez pas d’un seul champ token dans la table des utilisateurs. Les utilisateurs possèdent plusieurs appareils, et l’état de ces appareils évolue.

La stratégie de rafraîchissement compte plus que ne l'admettent les tutoriels

Les recommandations officielles de l’écosystème laissent ici un vrai vide opérationnel. Le contenu existant sur les notifications push Expo explique rarement comment maintenir la validité des tokens à travers Cycles de revue de l’App Store et mises à jour OTA, ce qui est particulièrement important pour les équipes qui déploient des changements en direct, car la fiabilité des notifications push dépend de l’état actuel des tokens et de la synchronisation du backend, comme le souligne 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 dans 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é ne doivent pas être reléguées à la fin du 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 liés à la santé, à la fintech ou au commerce régulé.

L'analyse de Courier sur les lacunes des notifications Expo pour l'entreprise souligne un manque de conseils pratiques sur la journalisation du consentement, les pistes d'audit et la minimisation de l'exposition des payloads sensibles. La conclusion technique est simple :

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

Pour les équipes alignant les releases à plus large échelle des stores et les pratiques de sécurité API, le push doit être intégré à la même discipline 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 la même rigueur que l'état d'auth et les événements de paiement.

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

Fonctionne généralement Casse généralement
Demander la permission après avoir expliqué clairement la valeur ajoutée Afficher le prompt dès la première frame
Tester sur des appareils réels Faire confiance à l’enregistrement du simulateur
Stocker les tokens avec le contexte de l’appareil Un token par enregistrement utilisateur
Envoyer des payloads de métadonnées légères Intégrer des blobs volumineux ou sensibles
Gérer les événements au premier plan et de tap séparément Assuming all notifications follow one path
Expirez agressivement les tokens obsolètes Réessayez indéfiniment les tokens morts

Une configuration solide des push Expo n’est pas compliquée. Elle est disciplinée.


Si votre équipe déploie fréquemment des changements de logique applicative et a besoin d’un meilleur contrôle sur le comportement des releases, les rollbacks et la visibilité de la livraison, Capgo mérite le détour. Il aide les équipes mobiles à pousser des mises à jour rapidement sans attendre la revue 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

Lorsqu'un bug de la couche web est en ligne, 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 offre les meilleures informations pour créer une application mobile vraiment professionnelle.