Connect a customer-owned Firebase project
- Open Settings > Channels > Push > Mobile apps as a workspace owner or admin.
- Enter the exact Firebase project ID and at least one Android package name or iOS bundle ID.
- Create a dedicated Firebase service account with only the permission needed for FCM HTTP v1 sending, then paste its JSON into the protected setup form.
- For iOS, configure your APNs authentication key inside that customer-owned Firebase project. Do not send the APNs key to Wepy.
- Store the one-time Wepy identity-signing secret in approved backend secret storage and acknowledge the backup before leaving setup.
- Integrate the signed enrollment contract and grant notification permission from a meaningful in-app action. Current Android and iOS apps use manual register() callbacks and enroll the Firebase Installation ID with fcmTargetType FID. REGISTRATION_TOKEN is legacy compatibility only for already-shipped clients.
- Create a pairing code on that exact device, enter it in Wepy, and send a controlled test. The first FCM-accepted test activates campaign sending.
Firebase remains BYOK
The Firebase project, service account, Android/iOS application identity, provider usage, and provider billing remain yours. Wepy encrypts the credential for this workspace and never exposes it through Sending accounts, list APIs, queues, analytics, or logs.
A real test completes setup
A new connection stays Needs attention until a real notification is accepted for a paired test installation. A successful OAuth exchange alone does not prove that the Firebase project, app identity, registration identifier, target type, and platform configuration work together. Accepted means FCM accepted the request; it is not proof that a device displayed it.
Implement consent, identity, and registration lifecycle
- Request native notification permission only after explaining the value in context. Record the exact app preference or native prompt provenance; an existing OS grant is not permission to silently restore a Wepy marketing opt-in.
- Have the authenticated customer backend mint a five-minute, one-use enrollment assertion bound to publicAppId, platform, fcmTargetType, the exact registration-identifier hash, iat, exp, and jti. Never put the identity-signing secret in the app binary.
- For current Android Firebase Messaging 25.1.2 or newer, keep auto-init disabled in the manifest and reassert it at runtime, disable Firebase Analytics collection before consent, enable installation-ID mode, and declare WepyMessagingService for com.google.firebase.MESSAGING_EVENT. Persist consent and every onRegistered()/onUnregistered() callback receipt—even when the FID repeats—plus opt-out intent and immutable request attempts in one encrypted transactional journal. Reconcile through a unique WorkManager chain, make Wepy revocation the authoritative opt-out boundary, track provider cleanup separately, and submit the FID with fcmTargetType FID.
- For current iOS Firebase Messaging 12.18.0 or newer, set FirebaseMessagingAutoInitEnabled to NO and FirebaseMessagingInstallationIdEnabled to YES in Info.plist, explicitly set auto-init to false again before assigning MessagingDelegate on every startup, and keep UIKit/Firebase access on MainActor. Persist every optional didReceiveRegistration callback receipt in order—even when the FID repeats—alongside immutable request attempts in a Keychain-backed actor. Reconcile through a Swift 6-safe FIFO coordinator, bridge BGTask expiration to cancellation, and submit a valid FID with fcmTargetType FID.
- Legacy compatibility only: already-shipped iOS or older Android clients may continue submitting an opaque FCM registration token with fcmTargetType REGISTRATION_TOKEN. New Android and iOS integrations must use FID.
- Persist the returned installation ID and revocation capability in platform-appropriate secure storage together with a monotonic consent epoch, FID version, and any uncertain immutable request attempt. Reuse the prior capability when Firebase reports a replacement identifier. Use the original durable consent evidence to decide EXISTING_PERMISSION and topicIds; never infer fresh topic authorization from capability presence.
- Before each Wepy POST, persist its exact body and stable idempotency key. If a response is lost or local finalization fails, replay the same operation so Wepy can return the same result; do not create a new key merely because the outcome is uncertain. If its embedded assertion later expires, supersede it only after an authoritative response proves that the old key has no committed receipt. Recheck consent epoch and FID version when committing the response, and journal a stale returned capability for revocation instead of activating it.
- On marketing opt-out, durably persist OPT_OUT_PENDING and increment the consent epoch before any network request. Resolve uncertain enrollment and revoke every known Wepy capability with a stable key; that authoritative commit atomically clears the capability and persists OPTED_OUT. Keep Firebase auto-init disabled and journal provider cleanup separately as pending, attempting, confirmed, uncertain, or needs attention. Firebase Messaging exposes no typed already-unregistered error, so retry only a provably pre-commit failure; never swallow generic unknown errors, parse localized error text, or blindly replay a crash-ambiguous attempt. Startup retries safe pending Wepy cleanup while ambiguous or permanent Firebase cleanup requires protected telemetry or authoritative control-plane reconciliation.
- Use a separate installation-bound identity assertion after sign-in. Call detach before logout or account switching so the shared device cannot receive the previous customer's personalized content.
- Send explicit unsubscribe, topic changes, display/open/click events, and conversion events through their purpose-limited native endpoints with a stable idempotency key.
- Treat an Invalid or Expired installation as local to that device. Another reachable browser or mobile installation for the contact can remain subscribed.
Device capability stays private
Wepy shows app/platform, bounded capability labels, reachability, consent, and timestamps. Raw Firebase registration identifiers, revocation capabilities, event tokens, service-account keys, and device fingerprints remain hidden. Contact 360 separates Web reach, Mobile reach, and the combined contact-level state.
Use the unified Push workflow
- Create or reuse one Push template with title, body, destination, optional rich media, and explicit personalization fallbacks. Web Push can also use dynamic action buttons; Mobile Push currently uses the main notification tap.
- Select a ready Web or Mobile app in the campaign sender step. Topics are scoped to that application and include only contacts who explicitly opted in.
- Optionally add deterministic A/B variants, a collapse key, quiet hours, a cross-channel frequency cap, and the evidence-gated recommended send time. Browser icon URLs and renotify are Web Push-only; Mobile Push uses its installed app icon and Normal or High urgency.
- Send the exact saved draft to your paired test device, review reachable contacts and exclusions, then send now or schedule.
- Reuse the saved campaign in an Automation. Wepy freezes the app, topic, target, content, and delivery policy and rechecks current consent and reachability at execution time.
- Read Results as targeted, excluded, provider accepted, signed presentation callback, opened/clicked, and conversion. For Web Push, the presentation callback means showNotification() resolved even though operating-system settings may suppress visible UI. Mobile integrations report it only when presentation can be directly confirmed. The callback is not proof that a person saw the notification; a signed click is human-interaction proof. Never read provider acceptance as delivered.
Optimization stays explainable
Recommended timing uses bounded recent Web and Mobile Push engagement only when the saved minimum evidence exists. Otherwise Wepy sends at the normal time. Experiments keep the same contact in the same variant across retries and all of that contact's devices.
Rotate or pause safely
Rotate Firebase credentials deliberately
Rotate a Firebase service account through the Mobile Push application, not generic Sending accounts. The action is replay-safe after an interrupted response and keeps the app identity and installation mappings unchanged. Revoke the previous Google credential only after the new credential is stored and a controlled test passes.
Do not strand lifecycle controls
Identity-signing-secret rotation returns the new value once and keeps the previous value valid for the exact 24-hour overlap shown by Wepy. Pausing stops registration, tests, campaigns, and automations, but privacy cleanup remains available so an installed app can still unsubscribe or detach.