SDK / Godot

Push notifications

ExperimentalGodot 4.7+

Your game asks the player to allow its notifications, and from then on the device is registered with Brain for the signed-in player: on iOS through Apple's push service (APNs) with your own key, on Android through Firebase Cloud Messaging. When the player opens a notification your game hears about it, with the data the notification carried.

Today Brain sends one kind of notification: a test from your studio console, to check that a device gets them. Campaigns, scheduled and targeted sends from your servers come later, and so do local notifications.

Turn push on

Add [push] to brain/game.toml:

[push]
# Android: your Firebase project's ids, from the Firebase console's project settings.
firebase_project_id = "neon-drift"
firebase_app_id = "1:123456789012:android:0a1b2c3d4e5f6a7b"
firebase_api_key = "AIzaSy..."
firebase_sender_id = "123456789012"
# Android's small notification icon: white on transparent. Without one, Android shows a bell.
android_icon = "brain/push-icon.png"

These ids are public, as Firebase's own config files are: put no keys here. iOS needs nothing in [push]: it sends to your app's bundle id, stores.appstore.bundle_id. Devices register under a player's Brain account, so the game needs accounts on ([accounts], or any matchmaking queue, leaderboard, saves or products); a guest account is enough.

Your studio's keys go on the console's Secrets page, or with ase studio secret. Set them for the studio, or for one game where it has its own:

Secret What it is
PUSH_APNS_KEY Your APNs auth key, the .p8 file (App Store Connect, Users and Access, Integrations, Keys)
PUSH_APNS_KEY_ID That key's id
PUSH_APNS_TEAM_ID Your Apple team id
PUSH_FCM_SERVICE_ACCOUNT A service account key file of your Firebase project, with the Firebase Cloud Messaging API Admin role
ase studio secret PUSH_APNS_KEY < AuthKey_ABC123DEFG.p8
ase studio secret PUSH_FCM_SERVICE_ACCOUNT --game neon-drift < firebase-service-account.json

Your game's Push page in the console says whether iOS and Android are ready and what is still missing.

Ask for permission

The SDK never asks on its own and shows nothing before the system's prompt: ask when the player understands why, such as after they finish a match they could be told about.

func _on_notify_me_pressed() -> void:
	var status := await Brain.push.request_permission()
	if status == "denied":
		show_hint("Notifications are off. You can turn them on in Settings.")

Brain.push.status says where the player stands:

Status Means
undetermined Never asked: request_permission() shows the system's prompt
granted Allowed; the device registers with Brain
provisional iOS's quiet notifications, delivered without asking; registers like granted
denied The player said no, or turned them off in Settings; asking again shows nothing
unsupported No push here: desktop, the web and Steam, or a game without [push]

Android 12 and older, where notifications need no permission, answer granted at once.

status_changed fires when the answer changes. Brain.push.supported() tells whether to show your notifications option at all.

Registering devices

Once notifications are allowed, the SDK registers the device with Brain as soon as a player is signed in. It sends again only when the device's push token, its build (development or App Store) or the player changes, so a game starting sends nothing new. A device belongs to one player at a time: when another player signs in on it, it moves to them.

For a notifications toggle in your own settings:

Brain.push.unregister()   # this device stops getting the player's notifications
Brain.push.register()     # and gets them again

unregister() holds across restarts until register().

Opened and received notifications

func _ready() -> void:
	Brain.push.opened.connect(_on_push_opened)
	Brain.push.received.connect(_on_push_received)

func _on_push_opened(pushed: Dictionary) -> void:
	# The player tapped it: {title, body, data}, data being the strings the sender attached.
	if pushed.data.get("screen") == "shop":
		open_shop()

func _on_push_received(pushed: Dictionary) -> void:
	# It arrived while the game was in front, where the system shows nothing.
	show_toast(pushed.title)

The notification that launched the game arrives as opened too, once Brain is ready. Each opened notification also sends a push_opened event to your analytics, saying whether it was a console test.

Send a test

On the console's Push page, the devices that registered most recently each have Send test. The notification says "Test notification" and carries brain_test in its data. The page then shows whether Apple or Google accepted it; whether it shows depends on the device's settings. Sending a test needs a role that manages games, and each one lands in the audit log.

Every notification Apple or Google accepts counts as a push send on your studio's usage.

Exports

Android

Use Godot's Gradle build. The editor plugin adds the push plugin and Firebase's messaging library to the export, writes your Firebase ids into the build as resources (no google-services.json) and copies your android_icon. The export warns when an id is missing; such a build gets no token.

iOS

Turn on Entitlements > Push Notifications in your iOS export preset: Development for builds signed for your own devices, Production for the App Store. An export of a game with [push] reports an error while it is Disabled. ase release sets it from your provisioning profile, and refuses a profile whose App ID lacks Push Notifications.

Development-signed builds register with Apple's sandbox, App Store and TestFlight builds with production; Brain sends each to the right one.