Ajouter les notifications push OneSignal à une web app Claude Code avec WebViewGold
Le push est la fonctionnalité native que les reviewers remarquent en premier, et celle que les utilisateurs gardent vraiment activée. Avec WebViewGold, OneSignal tourne dans la coque native ; votre web app décide seulement quand demander l'autorisation, à quel utilisateur appartient un appareil et quel écran une notification ouvre. Claude Code peut écrire tout cela en une seule session, et ce guide vous donne le prompt, le code serveur et le plan de test.
Dès $109 en paiement unique par plateforme, ou notre équipe s'occupe de tout dès $698.
Garantie d'approbation – ou remboursement sous 14 jours
Aucun codage requis
Paiement unique, mises à jour gratuites
Support humain 24/7
Conçu en Allemagne depuis 2014 · ISO 27001
9:41
Votre app
Votre appDésormais dans votre poche
App Store · Google Play Approuvée
Ce que vous connectez, et pourquoi les reviewers y tiennent
WebViewGold intègre le SDK OneSignal dans les deux projets natifs. Une fois le service activé, l'app reçoit les push même lorsqu'elle est fermée. Votre web app garde la main sur trois décisions : quand la demande d'autorisation du système apparaît, à quel utilisateur appartient un appareil et quelle URL une notification ouvre. Chacune passe par un schéma d'URL ou une variable JavaScript injectée, documentés dans la documentation push iOS et la documentation push Android.
Les reviewers y tiennent pour deux raisons. La guideline 4.2 attend d'une app basée sur le web qu'elle fasse plus qu'un site web, et une demande d'activation du push qui fonctionne est généralement la première capacité native qu'ils voient. La guideline 4.5.4 fixe les limites : l'app doit fonctionner sans push, les notifications ne doivent pas contenir de données personnelles sensibles, et les push promotionnels exigent un consentement explicite dans votre interface ainsi qu'un moyen de se désinscrire. Android 13 et les versions suivantes ajoutent une autorisation à l'exécution (POST_NOTIFICATIONS) : le moment de votre demande compte donc sur les deux plateformes.
Le flux que vous obtiendrez : après l'onboarding, la web app navigue vers registerpush:// ; une fois que l'utilisateur a accepté, elle lit onesignalplayerid et l'enregistre sur l'utilisateur ; votre serveur envoie un push à cet ID d'abonnement avec une url dans les données additionnelles, et WebViewGold ouvre cette URL quand on touche la notification. Pour une vue d'ensemble des fonctionnalités natives, consultez le hub des notifications push.
Ce que fait Claude Code et ce que vous faites
Domaine
Claude Code
Vous
Dashboard OneSignal
Rien : il n'a pas accès à votre dashboard
Créer l'app, ajouter les identifiants APNs (iOS) et Firebase (Android), copier l'App ID et créer une clé REST API
Projets WebViewGold
Peut définir kPushEnabled, oneSignalID, PUSH_ENABLED et l'ID dans build.gradle si les projets se trouvent dans le dépôt ; vous relisez le diff
Capabilities dans l'Apple Developer portal, bundle ID de l'extension OneSignal, signature et builds
Web app
Helper push, écran d'activation, ligne dans les réglages, route d'enregistrement, helper d'envoi, migration de base de données, règles dans CLAUDE.md
Approuver le plan, définir les variables d'environnement, déployer
Tests
Un plan de test écrit et, sur demande, une page de debug masquée qui affiche l'état du push et l'ID d'abonnement
Un vrai iPhone et un vrai téléphone Android, TestFlight et les tests internes
Activez OneSignal et laissez Claude Code s'occuper de la partie web
Comptez environ une heure, passée surtout dans les consoles d'Apple et de Firebase.
Créez une seule app OneSignal pour les deux plateformes
Ajoutez iOS avec vos identifiants APNs (OneSignal recommande une clé d'authentification .p8 ; un certificat push fonctionne aussi) et Android avec le fichier JSON du compte de service Firebase que OneSignal demande. Copiez l'App ID OneSignal et créez une clé REST API pour votre serveur.
iOS : Config.swift et capabilities
Réglez kPushEnabled sur true, collez l'App ID dans oneSignalID et réglez askforpushpermissionatfirstrun sur false pour choisir vous-même le moment de la demande. Dans l'Apple Developer portal, activez Push Notifications et App Groups pour l'App ID. La cible de l'extension OneSignal a besoin de votre bundle ID suivi de .OneSignalNotificationServiceExtension.
Android : Config.java et build.gradle
Réglez PUSH_ENABLED sur true, collez l'App ID dans ONE_SIGNAL_APP_ID du fichier build.gradle (Module: app) et réglez requirePush sur false. Remplacez ic_stat_onesignal_default.png par votre propre icône monochrome, sinon les utilisateurs voient une cloche générique.
Marquez l'app dans le user agent
Définissez useragent_iphone et useragent_ipad (iOS) ainsi que USER_AGENT (Android) sur un user agent mobile classique suivi de WebViewGoldApp, pour que isNativeApp() puisse distinguer l'app de Safari ou de Chrome. Le modèle CLAUDE.md explique cette convention.
Lancez le prompt en mode plan
Appuyez sur Shift+Tab jusqu'à ce que Claude Code affiche le mode plan (ou démarrez-le avec claude --permission-mode plan), collez le prompt ci-dessous et n'approuvez le plan que s'il liste les fichiers et la table que vous attendez. Laissez-le ensuite implémenter, lisez le diff et déployez.
Compilez et installez
Archivez l'app iOS pour TestFlight et envoyez le bundle Android en test interne. Si vous préférez ne pas installer Xcode et Android Studio pour cela, le Cloud Builder compile les deux apps dans le navigateur et les envoie pour vous.
Excellente façon de convertir son app web en app native ! Un délai très court, et un super moyen de mettre ses apps dans les stores sans devoir développer une app native complète !
Kevin Joling · FlightConnections & TrainConnections · Trustpilot
Le prompt Claude Code
Adaptez le nom de la table, les routes et les exemples de notifications à votre app. Le prompt indique à l'agent où se trouvent les noms de schémas qui font foi, pour qu'il n'en invente aucun.
À coller dans Claude Code (d'abord en mode plan)
Notre web app tourne aussi dans des apps natives iOS et Android construites avec WebViewGold. Le push OneSignal est activé dans les projets natifs. La web app doit demander l'autorisation au bon moment et transmettre l'ID d'abonnement (subscription ID) de l'appareil à notre serveur, et le serveur envoie des notifications ciblées. Avant d'écrire du code, lisez les sections Push Notifications pour iOS et Android dans https://www.webviewgold.com/llms-full.txt et n'utilisez que les schémas d'URL et les variables qui y sont documentés. Commencez par un plan et attendez mon approbation.
Implémentez :
1. src/lib/native.ts (réutilisez-le s'il existe) : isNativeApp() cherche le jeton WebViewGoldApp dans navigator.userAgent ; callNative(url) définit window.location.href uniquement dans l'app ; readInjected(name, timeoutMs) interroge window[name] toutes les 100 ms et rejette la promesse une fois le délai écoulé.
2. src/lib/push.ts : askForPush() navigue vers registerpush://. getPushStatus() navigue vers checkNativePushPermissions:// et résout avec window.nativePushEnabled (true ou false). syncPushId() navigue vers getonesignalplayerid://, lit window.onesignalplayerid et l'envoie en POST avec la plateforme (ios ou android, d'après le user agent) à /api/push/register. Ne déclenchez jamais deux schémas dans la même exécution de script : sur iOS, plusieurs appels à window.location.href dans un même script ne fonctionnent pas, enchaînez-les donc avec un délai d'environ une seconde.
3. Un écran d'activation affiché une seule fois après l'onboarding, jamais sur le premier écran, uniquement quand isNativeApp() vaut true : une phrase sur ce que nous envoyons (mises à jour de commande et réponses), un bouton Activer les notifications (askForPush, puis syncPushId après 3 secondes) et un lien Plus tard qui masque l'écran pendant 14 jours via localStorage.
4. Réglages : une ligne Notifications qui affiche l'état renvoyé par getPushStatus(). Quand les notifications sont désactivées, affichez Ouvrir les réglages, qui navigue vers settingsapp://. Ajoutez un interrupteur distinct Actualités produit, désactivé par défaut et enregistré sur le profil utilisateur ; seuls les utilisateurs qui l'ont activé peuvent recevoir des push promotionnels (guideline Apple 4.5.4).
5. À chaque démarrage de l'app par un utilisateur connecté, dans l'app, appelez syncPushId() une fois, car l'ID d'abonnement peut changer après une réinstallation.
6. Serveur : POST /api/push/register (authentifié ; upsert de user_id, subscription_id, platform, last_seen_at dans une table push_devices ; ajoutez la migration) et un helper réservé au serveur sendPushToUser(userId, title, message, path) qui appelle l'API REST de OneSignal avec include_subscription_ids et place l'URL https complète de l'écran cible dans data.url. Lisez ONESIGNAL_APP_ID et ONESIGNAL_REST_API_KEY uniquement depuis les variables d'environnement du serveur.
7. Appelez sendPushToUser là où une nouvelle réponse ou un changement de statut de commande est créé. Aucun détail personnel ou sensible dans le texte de la notification.
8. Ajoutez les règles push ci-dessus à CLAUDE.md.
Indiquez les fichiers modifiés, la migration, les variables d'environnement que je dois définir et tout ce que vous n'avez pas pu vérifier.
La route d'enregistrement et le helper d'envoi
Next.js App Router avec TypeScript ; demandez à l'agent de l'adapter à Express, à une Supabase Edge Function ou à une Cloud Function si c'est votre stack. La valeur data.url est ce que WebViewGold ouvre quand on touche la notification ; le champ Launch URL de OneSignal n'est pas celui à utiliser.
typescript
// app/api/push/register/route.ts (appelée par la web app dans la coque native)
import { NextResponse } from "next/server";
import { getUser, db } from "@/lib/server"; // vos helpers d'authentification et de base de données
export async function POST(req: Request) {
const user = await getUser(req);
if (!user) return NextResponse.json({ error: "unauthorized" }, { status: 401 });
const { subscriptionId, platform } = await req.json();
if (typeof subscriptionId !== "string" || subscriptionId.length < 10) {
return NextResponse.json({ error: "invalid subscription id" }, { status: 400 });
}
await db.pushDevices.upsert({ userId: user.id, subscriptionId, platform, lastSeenAt: new Date() });
return NextResponse.json({ ok: true });
}
// lib/push-server.ts (serveur uniquement, ne jamais importer depuis des composants client)
export async function sendPushToUser(userId: string, title: string, message: string, path: string) {
const devices = await db.pushDevices.findMany({ userId });
if (devices.length === 0) return { sent: 0 };
const res = await fetch("https://api.onesignal.com/notifications?c=push", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Key " + process.env.ONESIGNAL_REST_API_KEY,
},
body: JSON.stringify({
app_id: process.env.ONESIGNAL_APP_ID,
include_subscription_ids: devices.map((d) => d.subscriptionId),
headings: { en: title },
contents: { en: message },
data: { url: "https://app.example.com" + path }, // ouverte par WebViewGold quand on touche la notification
}),
});
if (!res.ok) throw new Error("OneSignal " + res.status + ": " + (await res.text()));
return { sent: devices.length };
}
Checklist de vérification sur de vrais téléphones
Ni les simulateurs ni les navigateurs desktop ne peuvent prouver quoi que ce soit ici. Utilisez le build TestFlight sur un iPhone et le build de test interne sur un téléphone Android 13 ou plus récent, tous deux fraîchement installés.
Premier lancement : aucune demande du système n'apparaît, car askforpushpermissionatfirstrun et requirePush sont sur false.
Après l'onboarding, votre écran d'activation apparaît ; Activer les notifications affiche la boîte de dialogue du système ; Plus tard masque l'écran, qui reste masqué au lancement suivant.
Après acceptation, une ligne apparaît dans push_devices et l'appareil figure dans OneSignal sous Audience → Subscriptions.
Envoyez un test depuis le dashboard OneSignal avec, dans Additional data, url pointant vers une page profonde comme /orders/42. Touchez la notification trois fois : app fermée, en arrière-plan et au premier plan. Chaque toucher ouvre cette page dans l'app.
Déclenchez un vrai événement (une réponse à l'utilisateur de test) et vérifiez que seuls les appareils de cet utilisateur reçoivent le push.
Sur un second appareil, refusez l'autorisation : les réglages indiquent que les notifications sont désactivées et Ouvrir les réglages mène à l'écran du système via settingsapp://. Réactivez-les là-bas, revenez : l'état se met à jour.
Supprimez et réinstallez l'app, connectez-vous : un nouvel ID d'abonnement est enregistré.
Pièges
Deux schémas dans une même exécution de script sur iOS. Assigner plusieurs schémas à window.location.href dans le même script ne fonctionne pas sur iOS (Android, lui, le gère). Enchaînez les appels avec un délai, ou utilisez le schéma documenté multiapicall://getonesignalplayerid,getappversion pour les appels de données pris en charge (documentation MultiAPICall).
Launch URL au lieu des données additionnelles. WebViewGold lit le champ url des données additionnelles. Laissez kPushOpenDeeplinkInBrowser (iOS) et OPEN_NOTIFICATION_URLS_IN_SYSTEM_BROWSER (Android) sur false si les liens doivent s'ouvrir dans l'app.
Lire l'ID trop tôt.onesignalplayerid est injecté de façon asynchrone et peut ne pas exister tant que le SDK ne s'est pas enregistré. Interrogez la variable avec un délai maximal et réessayez au prochain démarrage de l'app au lieu d'échouer en silence.
Compter sur le paramètre d'URL. Avec kPushEnhanceUrl ou PUSH_ENHANCE_WEBVIEW_URL, seule la première requête reçoit ?onesignal_push_id=… ; un routeur côté client le perd. Enregistrez-le tout de suite dans un cookie ou une session, ou utilisez autoInjectVariable / AUTO_INJECT_VARIABLES.
Un service push non activé.registerpush:// ne fait rien si aucun service push n'est activé dans le wrapper. Vérifiez la configuration avant de déboguer votre JavaScript.
Des secrets dans le client. La clé REST API a sa place uniquement dans les variables d'environnement du serveur. Claude Code n'a jamais besoin de la vraie valeur ; donnez-lui le nom de la variable.
Questions fréquentes
Puis-je utiliser Firebase Cloud Messaging au lieu de OneSignal ?
Oui. Activez kFirebasePushEnabled dans Config.swift avec votre GoogleService-Info.plist, et FIREBASE_PUSH_ENABLED dans Config.java avec votre google-services.json. Côté web, rien ne change, sauf que l'ID provient de getfirebaseplayerid:// sous le nom firebaseplayerid.
Le push est-il obligatoire pour être accepté sur l'App Store ?
Non, et l'app ne doit pas en dépendre (guideline 4.5.4). C'est pourtant l'un des signaux les plus forts, au regard de la guideline 4.2, que votre app est plus qu'un site web.
Puis-je envoyer des notifications sans serveur ?
Oui. Les envois groupés depuis le dashboard OneSignal ne demandent aucun code, et les rappels locaux programmés avec sendlocalpushmsg:// fonctionnent sans aucun service push. Un serveur n'est nécessaire que pour les messages adressés à un utilisateur précis.
Pourquoi ne pas demander l'autorisation au premier lancement ?
iOS n'affiche la boîte de dialogue du système qu'une seule fois. Si l'utilisateur refuse parce qu'il ne connaît pas encore votre app, seuls les réglages du système permettent de revenir dessus. Demander après un moment qui montre l'intérêt des notifications convertit bien mieux.
Le web push d'un service worker fonctionne-t-il dans l'app ?
Ne comptez pas dessus. Dans l'app WebViewGold, le push est natif, via OneSignal, Firebase ou Pushwoosh. Si vous utilisez le web push, réservez-le aux visiteurs dans le navigateur.
Trois façons de mettre votre app dans les stores
Même résultat, charge de travail différente de votre côté. Les trois formules incluent la garantie d'approbation et le support humain 24/7.
Faites-le vous-même
$109 par plateforme, paiement unique
La licence WebViewGold : un projet Xcode ou Android Studio prêt à l'emploi. Collez votre URL, définissez le nom et l'icône, activez les fonctionnalités, compilez et soumettez. Mises à jour gratuites à vie.
Ni Mac, ni Xcode, ni Android Studio : configurez dans le navigateur, nous compilons les deux apps dans le cloud et les transmettons à App Store Connect et à la Play Console.
Envoyez-nous votre URL et votre icône. Notre équipe configure, compile et livre votre app sous 72 heures, en marque blanche, projets sources inclus. Les deux plateformes pour $1,158.
Les remboursements sont accordés aux conditions indiquées dans notre FAQ : un refus non lié au contenu par Apple et/ou Google, demandé dans les 14 jours suivant l'achat.