Push Notifications are a great way to keep your users engaged with your application. Countly Push Notifications gives product managers, marketers, and developers a simple way to send, manage, and analyze push notifications for applications on the world's most popular platforms - iOS, Android, and Huawei devices.
Countly relies on platform-specific push notification providers to deliver messages:
- APN (Apple Push Notification service) - for iOS, iPadOS, watchOS, tvOS, and macOS apps
- FCM (Firebase Cloud Messaging) - for Android apps with Google Play Services
- HMS (Huawei Mobile Services) - for Huawei devices without Google Play Services
This guide walks you through the complete setup - from acquiring provider credentials and uploading them to your Countly Server, to integrating the SDK in your application.
Availability: Push Notifications are available in Countly Lite, Countly Enterprise, and as an add-on in Flex. Countly Lite has limited feature and view availability. Enterprise Edition includes additional geolocations support.
How Push Notifications Work
When a user opens your app for the first time, the Countly SDK automatically retrieves a device token from the respective push notification provider (Firebase or Huawei Push Kit for Android, APN for iOS) and sends it to your Countly Server for storage. A token is unique to a device, meaning it identifies that particular device.
The high-level flow is:
- Your App (SDK) - retrieves a device token from the provider on first launch.
- APN / FCM / HMS - issues the token to the device.
- Countly Server - stores the token and uses your uploaded credentials to send notification payloads.
- APN / FCM / HMS - delivers the notification to the user's device.
Token retrieval and submission to the Countly Server are handled automatically by the Countly SDK. You won't need to worry about this process once you have integrated the Countly SDK properly as shown in the steps below.
Select your provider:
Server Side Setup
To send push notifications to Android devices, you need a Firebase project with your Android app registered and the Firebase Cloud Messaging API (V1) enabled. Countly uses the FCM HTTP v1 API, which requires a Service Account JSON file from your Firebase project.
- Open the Firebase Console and select your project.
- Go to Project Settings (gear icon) > Service accounts tab.
- Click Generate new private key and confirm. A JSON file will be downloaded - store it securely.
- Ensure that the Firebase Cloud Messaging API (V1) is enabled for your project. You can verify this in the Google Cloud Console API Library.
- In the Countly Dashboard, navigate to Management > Applications > Your App > Push Notifications. Upload the Service Account JSON file under the FCM section and click Save changes.
Important: Do not confuse google-services.json (used by the client SDK in your app) with the Service Account JSON (used by the server to send notifications). They are different files. The Service Account JSON is the one downloaded from the Service accounts tab in the Firebase Console.
To send push notifications to iOS devices, you need an active Apple Developer Account. Countly supports two authentication methods for APN: Auth Key (.p8) and Certificate (.p12). We strongly recommend using the Auth Key approach - it does not expire, works for both sandbox and production environments, and is simpler to manage.
- Sign in to the Apple Developer Portal and navigate to Certificates, Identifiers & Profiles > Keys.
- Click the + button to create a new key. Enable Apple Push Notifications service (APNs), give it a name, and click Register.
- Download the
.p8file. You can only download this file once, so store it securely. - Note the Key ID (shown on the key details page), your Team ID (found under Membership Details), and the Bundle ID of your app.
- In the Countly Dashboard, go to Management > Applications > Your App > Push Notifications. Upload the
.p8file, and fill in the Key ID, Team ID, and Bundle ID fields. Click Save changes.
Countly will validate the credentials by initiating a test connection to APN. If validation fails, double-check that the Key ID, Team ID, and Bundle ID are correct.
If you need to use the certificate-based approach, you will need a Universal (Sandbox & Production) push certificate exported as a .p12 file without a password.
- In the Apple Developer Portal, navigate to Certificates, Identifiers & Profiles > Certificates.
- Click + and choose Apple Push Notification service SSL (Sandbox & Production).
- Select the App ID for your application and follow the wizard to generate the certificate.
- Download the certificate and install it in your Keychain.
- In Keychain Access, find the certificate, expand it to reveal the private key, select both, right-click and choose Export 2 items... as a
.p12file. Do not set a password. - Upload the
.p12file to the Countly Dashboard under Management > Applications > Your App > Push Notifications.
Note: Certificates expire after one year and must be renewed. Auth Keys do not expire. Countly does not support development-only certificates - always use a Universal (Sandbox & Production) certificate.
To send push notifications to Huawei devices, you need a Huawei AppGallery Connect project with Push Kit enabled.
- Sign in to Huawei AppGallery Connect, select your project, and navigate to Grow > Push Kit.
- Enable Push Kit if it is not already enabled.
- Navigate to Project settings > General information to find your App ID and App Secret (under App information).
- In the Countly Dashboard, navigate to Management > Applications > Your App > Push Notifications. Enter the App ID and App Secret under the HMS section and click Save changes.
SDK Side Setup
All code samples assume you have already integrated the Countly SDK into your project. If you haven't, please refer to the Getting Started with SDKs guide first.
Select an SDK:
Make sure you have followed Google's guide for adding Firebase to your project. Then add the Firebase Messaging dependency to your app-level build.gradle:
// app/build.gradle
// use the latest firebase-messaging version that is available
implementation 'com.google.firebase:firebase-messaging:LATEST_VERSION'
Add a service definition to your AndroidManifest.xml:
<service android:name=".DemoFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Add a class for the service:
public class DemoFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onNewToken(@NonNull String token) {
super.onNewToken(token);
CountlyPush.onTokenRefresh(token);
}
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
CountlyPush.Message message = CountlyPush.decodeMessage(remoteMessage.getData());
if (message != null) {
message.recordAction(getApplicationContext());
CountlyPush.displayMessage(getApplicationContext(), message, R.drawable.ic_message, null);
}
}
}
Initialize CountlyPush in your Application class. Then initialize the Countly SDK as usual:
// In your Application.onCreate()
CountlyConfigPush countlyConfigPush = new CountlyConfigPush(this);
CountlyPush.init(countlyConfigPush);
CountlyConfig config = new CountlyConfig(this, "APP_KEY", "https://YOUR_SERVER");
Countly.sharedInstance().init(config);
Intent Redirection Security
By default, the Countly Android SDK enables additional intent redirection checks to protect against Intent Redirection Vulnerability. You can allowlist specific intents if needed:
CountlyConfigPush countlyConfigPush = new CountlyConfigPush(this)
.setAllowedIntentClassNames(allowedClassNames)
.setAllowedIntentPackageNames(allowedPackageNames);
CountlyPush.init(countlyConfigPush);
This section covers the Android (FCM) side of Flutter push notification setup. For the iOS (APNs) side, select the APN provider tab above.
SDK Configuration
Set the push token mode before initializing the SDK:
Countly.pushTokenType(Countly.messagingMode["PRODUCTION"]);
CountlyConfig config = CountlyConfig("https://YOUR_SERVER", "APP_KEY");
await Countly.initWithConfig(config);
Countly.askForNotificationPermission();
Setup
- Place
google-services.jsonin yourandroid/app/directory. -
Add the following at the bottom of
android/app/build.gradle:// At the bottom of the file apply plugin: 'com.google.gms.google-services' -
Add the Countly messaging service to your
android/app/src/main/AndroidManifest.xmlinside the<application>tag:<service android:name="ly.count.dart.countly_flutter.CountlyMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
This section covers the Android (FCM) side of React Native push notification setup. For the iOS (APNs) side, select the APN provider tab above.
SDK Configuration
import Countly from 'countly-sdk-react-native-bridge';
import CountlyConfig from 'countly-sdk-react-native-bridge/CountlyConfig';
const countlyConfig = new CountlyConfig("https://YOUR_SERVER", "APP_KEY");
// Android: Set notification channel info
countlyConfig.setPushNotificationChannelInformation(
"Channel Name",
"Channel Description"
);
await Countly.initWithConfig(countlyConfig);
Setup
- Place
google-services.jsoninandroid/app/. -
Add the following at the bottom of
android/app/build.gradle:apply plugin: 'com.google.gms.google-services'
Multiple messaging services: If you use other plugins for push notifications alongside Countly, you need to handle multiple FCM services. Please follow the instructions from the React Native Bridge documentation.
Intent Redirection Security
By default, additional intent redirection protection is enabled. You can disable it if needed (not recommended):
countlyConfig.disableAdditionalIntentRedirectionChecks();
The Countly Unity SDK uses FCM for Android. It does not support Huawei Push Kit. For the iOS (APNs) side, select the APN provider tab above.
SDK Configuration
CountlyConfiguration configuration = new CountlyConfiguration("APP_KEY", "https://YOUR_SERVER");
// Set notification mode
configuration.SetNotificationMode(TestMode.ProductionToken);
Countly.Instance.Init(configuration);
Setup
- Download
google-services.jsonfrom your Firebase Console. - Convert it to
google-services.xml. You can use an online converter. - Place the XML file in
Assets/Plugins/Android/Notifications/res/values/(replace the existing file if necessary).
Removing Dependencies
If you don't need push notifications on Android, delete the Assets/Plugins/Android/Notifications folder. Re-import the Unity package to restore. Don't forget to change the notification mode to TestMode.None after removing push notification dependencies.
Select an SDK:
Xcode Configuration
Under the Signing & Capabilities section of Xcode, enable the following for your target:
- Click + Capability and add Push Notifications.
- Click + Capability again and add Background Modes. Enable Remote notifications.
SDK Initialization
Start Countly in the application:didFinishLaunchingWithOptions: method of your app. Do not forget to specify CLYPushNotifications in the features array on the CountlyConfig object:
#import "Countly.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
CountlyConfig* config = CountlyConfig.new;
config.appKey = @"APP_KEY";
config.host = @"https://YOUR_COUNTLY_SERVER";
config.features = @[CLYPushNotifications];
[Countly.sharedInstance startWithConfig:config];
return YES;
}
Note: Make sure you start Countly iOS SDK on the main thread.
The Countly iOS SDK handles everything automatically - requesting notification permission, retrieving the device token, processing incoming notifications, and managing Notification Service Extensions for rich push (media attachments and custom action buttons).
This section covers the iOS (APNs) side of Flutter push notification setup. For the Android (FCM) side, select the FCM provider tab above.
SDK Configuration
Set the push token mode before initializing the SDK:
Countly.pushTokenType(Countly.messagingMode["PRODUCTION"]);
CountlyConfig config = CountlyConfig("https://YOUR_SERVER", "APP_KEY");
await Countly.initWithConfig(config);
Countly.askForNotificationPermission();
Setup
Open the iOS project in Xcode (ios/Runner.xcworkspace) and add the Push Notifications capability and enable the Remote notifications background mode, as described in the iOS section.
This section covers the iOS (APNs) side of React Native push notification setup. For the Android (FCM) side, select the FCM provider tab above.
SDK Configuration
import Countly from 'countly-sdk-react-native-bridge';
import CountlyConfig from 'countly-sdk-react-native-bridge/CountlyConfig';
const countlyConfig = new CountlyConfig("https://YOUR_SERVER", "APP_KEY");
// iOS: Set token type
countlyConfig.setPushTokenType(Countly.messagingMode.PRODUCTION);
// Options: PRODUCTION, DEVELOPMENT, ADHOC
await Countly.initWithConfig(countlyConfig);
Setup
Open the iOS project in Xcode and add the Push Notifications capability and enable the Remote notifications background mode, as described in the iOS section.
The Countly Unity SDK uses APNs for iOS. For the Android (FCM) side, select the FCM provider tab above.
SDK Configuration
CountlyConfiguration configuration = new CountlyConfiguration("APP_KEY", "https://YOUR_SERVER");
// Set notification mode
configuration.SetNotificationMode(TestMode.ProductionToken);
Countly.Instance.Init(configuration);
Setup
- In Unity, go to Player Settings > Other Settings and add the
COUNTLY_ENABLE_IOS_PUSHsymbol to Scripting Define Symbols. - After exporting the iOS project, open it in Xcode and add the Push Notifications capability.
Removing Dependencies
If you don't need push notifications on iOS, delete the Assets/Plugins/iOS folder and remove the COUNTLY_ENABLE_IOS_PUSH symbol from Scripting Define Symbols. Re-import the Unity package to restore. Don't forget to change the notification mode to TestMode.None after removing push notification dependencies.
The Unity SDK does not support Huawei Push Kit.
Select an SDK:
Assuming you have already integrated HMS Core into your app, add the Huawei Push Kit dependency to your app-level build.gradle (use the latest dependency version):
implementation 'com.huawei.hms:push:LATEST_VERSION'
Add a service definition to AndroidManifest.xml:
<service
android:name=".DemoHuaweiMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
Add the service class:
public class DemoHuaweiMessagingService extends HmsMessageService {
@Override
public void onNewToken(String token) {
super.onNewToken(token);
CountlyPush.onTokenRefresh(token, Countly.CountlyMessagingProvider.HMS);
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
CountlyPush.Message message = CountlyPush.decodeMessage(remoteMessage.getDataOfMap());
if (message != null) {
message.recordAction(getApplicationContext());
CountlyPush.displayMessage(getApplicationContext(), message, R.drawable.ic_message, null);
}
}
}
Initialize CountlyPush with HMS as the preferred provider, then initialize the Countly SDK:
// In your Application.onCreate()
CountlyConfigPush countlyConfigPush = new CountlyConfigPush(this)
.setProvider(Countly.CountlyMessagingProvider.HMS);
CountlyPush.init(countlyConfigPush);
CountlyConfig config = new CountlyConfig(this, "APP_KEY", "https://YOUR_SERVER");
Countly.sharedInstance().init(config);
The Flutter SDK ships a built-in FirebaseMessagingService but does not include an HMS service. You can add HMS support by creating a native Android service in your Flutter project.
Setup
-
Add the HMS Push Kit dependency to your
android/app/build.gradle:implementation 'com.huawei.hms:push:LATEST_VERSION' -
Create a new Java file at
android/app/src/main/java/YOUR_PACKAGE/HuaweiMessagingService.java:package YOUR_PACKAGE; import com.huawei.hms.push.HmsMessageService; import com.huawei.hms.push.RemoteMessage; import ly.count.android.sdk.messaging.CountlyPush; import ly.count.android.sdk.Countly; public class HuaweiMessagingService extends HmsMessageService { @Override public void onNewToken(String token) { super.onNewToken(token); if (Countly.sharedInstance().isInitialized()) { CountlyPush.onTokenRefresh(token, Countly.CountlyMessagingProvider.HMS); } } @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); CountlyPush.Message message = CountlyPush.decodeMessage(remoteMessage.getDataOfMap()); if (message != null) { CountlyPush.displayMessage(getApplicationContext(), message, getApplicationContext().getApplicationInfo().icon, null); } } } -
Register the service in your
android/app/src/main/AndroidManifest.xmlinside the<application>tag:<service android:name=".HuaweiMessagingService" android:exported="false"> <intent-filter> <action android:name="com.huawei.push.action.MESSAGING_EVENT" /> </intent-filter> </service> -
Set the push token mode before SDK init as usual:
Countly.pushTokenType(Countly.messagingMode["PRODUCTION"]); CountlyConfig config = CountlyConfig("https://YOUR_SERVER", "APP_KEY"); await Countly.initWithConfig(config); Countly.askForNotificationPermission();
The native Android SDK detects HMS via reflection. If FCM is not available on the device, it will automatically try HMS. You can keep both the built-in CountlyMessagingService (FCM) and your custom HuaweiMessagingService (HMS) registered simultaneously to support both device types.
The React Native SDK ships a built-in FirebaseMessagingService but does not include an HMS service. You can add HMS support by creating a native Android service in your React Native project.
Setup
-
Add the HMS Push Kit dependency to your
android/app/build.gradle:implementation 'com.huawei.hms:push:LATEST_VERSION' -
Create a new Java file at
android/app/src/main/java/YOUR_PACKAGE/HuaweiMessagingService.java:package YOUR_PACKAGE; import android.content.Context; import com.huawei.hms.push.HmsMessageService; import com.huawei.hms.push.RemoteMessage; import ly.count.android.sdk.messaging.CountlyPush; import ly.count.android.sdk.Countly; public class HuaweiMessagingService extends HmsMessageService { @Override public void onNewToken(String token) { super.onNewToken(token); if (Countly.sharedInstance().isInitialized()) { CountlyPush.onTokenRefresh(token, Countly.CountlyMessagingProvider.HMS); } } @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); CountlyPush.Message message = CountlyPush.decodeMessage(remoteMessage.getDataOfMap()); if (message != null) { Context context = getApplicationContext(); CountlyPush.displayMessage(context, message, context.getApplicationInfo().icon, null); } } } -
Register the service in your
android/app/src/main/AndroidManifest.xmlinside the<application>tag:<service android:name=".HuaweiMessagingService" android:exported="false"> <intent-filter> <action android:name="com.huawei.push.action.MESSAGING_EVENT" /> </intent-filter> </service> -
Configure the SDK as usual:
import Countly from 'countly-sdk-react-native-bridge'; import CountlyConfig from 'countly-sdk-react-native-bridge/CountlyConfig'; const countlyConfig = new CountlyConfig("https://YOUR_SERVER", "APP_KEY"); countlyConfig.setPushNotificationChannelInformation("Channel Name", "Channel Description"); await Countly.initWithConfig(countlyConfig);
The native Android SDK detects HMS via reflection. If FCM is not available on the device, it will automatically try HMS. You can keep both the built-in CountlyMessagingService (FCM) and your custom HuaweiMessagingService (HMS) registered simultaneously to support both device types.
Customizing Notification Sound
Countly supports custom notification sounds on every platform that exposes a native sound API. The sound file must be present on the device — push payloads can reference it by name or URI, but cannot link to an audio file on the internet. The device-side setup is described below per platform; sending the sound is then done from the Countly Dashboard Send sound field when creating a push notification.
Custom sound files must ship inside the app bundle (iOS) or under the Android res/raw resource folder. They cannot be downloaded at notification time.
Place the sound file in your Android project's res/raw folder, then build the resource URI:
String soundUri = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getApplicationContext().getPackageName() + "/" + R.raw.notif_sound;
Send this URI in the Send sound field of the Countly Dashboard when creating a push notification. This covers devices running Android with SDK version below 26.
For Android SDK 26 and above, the sound is bound to the notification channel rather than the individual notification. Provide the same URI when you create the notification channel:
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(soundUri, audioAttributes);
iOS handles notification sound playback natively, so the supported audio formats are dictated by iOS itself: Linear PCM, MA4 (IMA/ADPCM), µLaw, and aLaw, packaged as aiff, wav, or caf files. See Apple's Preparing Custom Alert Sounds for the full list of constraints.
Add the audio file to your application target in Xcode (for example, exampleSound.wav), then enter the same filename in the Send sound field of the Countly Dashboard when creating a push notification.
Sound is also one of the permission types your app must request. When asking for notification permission with preferred types, include UNAuthorizationOptionSound in the authorization options:
UNAuthorizationOptions authorizationOptions = UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert;
[Countly.sharedInstance askForNotificationPermissionWithOptions:authorizationOptions completionHandler:^(BOOL granted, NSError *error) { /* handle result */ }];
Custom notification sound is currently supported on the Android side of Flutter only. Place the sound file in your Android project's res/raw folder, then pass the resource URI as the first parameter of Countly.askForNotificationPermission:
Countly.askForNotificationPermission("android.resource://PACKAGE_NAME/raw/NAME_OF_SOUND_WITHOUT_EXTENSION");
The SDK uses this URI to construct the channel sound on Android SDK 26 and above. Send the same sound name in the Send sound field of the Countly Dashboard when creating a push notification.
For the iOS side of a Flutter app, follow the iOS tab above: add the audio file to the iOS target and enter the filename in the Send sound field.
Custom notification sound is currently supported on the Android side of React Native only. Place the sound file in your Android project's res/raw folder, then pass the resource URI as the first parameter of Countly.askForNotificationPermission:
// CUSTOM_SOUND_PATH is an optional parameter and is currently supported only for Android.
Countly.askForNotificationPermission("android.resource://PACKAGE_NAME/raw/NAME_OF_SOUND_WITHOUT_EXTENSION");
The SDK uses this URI to construct the channel sound on Android SDK 26 and above. Send the same sound name in the Send sound field of the Countly Dashboard when creating a push notification.
For the iOS side of a React Native app, follow the iOS tab above: add the audio file to the iOS target and enter the filename in the Send sound field.
For Android, replace the default notification sound file inside Assets/Plugins/Android/Notifications/res in your Unity project. The notification channel name and description can be customized through the strings.xml file located at Assets/Plugins/Android/Notifications/res/values.
For iOS, add the audio file to the exported iOS project's app target in Xcode, then enter the filename in the Send sound field of the Countly Dashboard when creating a push notification.
User Consent
If your app requires GDPR compliance or uses Countly's consent management feature, you must grant the push consent for push notifications to function. Without this consent, the SDK will not send the device token to the server.
// Give push consent during initialization
config.setConsentEnabled(new String[]{"push"});
// Or after initialization
Countly.sharedInstance().consent().giveConsent(new String[]{"push"});
// Revoke consent
Countly.sharedInstance().consent().removeConsent(new String[]{"push"});// Give push consent during initialization
config.consents = @[CLYConsentPushNotifications];
// Or after initialization
[Countly.sharedInstance giveConsentForFeature:CLYConsentPushNotifications];
// Revoke consent
[Countly.sharedInstance cancelConsentForFeature:CLYConsentPushNotifications];// Give push consent during initialization
config.setConsentEnabled([CountlyConsent.push]);
// Or after initialization
Countly.giveConsent([CountlyConsent.push]);
// Revoke consent
Countly.removeConsent([CountlyConsent.push]);// Give push consent during initialization
countlyConfig.giveConsent(["push"]);
// Or after initialization
Countly.giveConsent(["push"]);
// Revoke consent
Countly.removeConsent(["push"]);// Give push consent during initialization
configuration.GiveConsent(new Consents[] { Consents.Push });
// Revoke consent
Countly.Instance.Consents.RemoveConsent(new Consents[] { Consents.Push });The Countly SDK does not persistently store the status of given consents except for push notifications. You are expected to handle receiving consent from end-users using proper UIs depending on your app's context, and call the giveConsent method on each app launch depending on the permissions you managed to get from the end-users.
Separating Marketing and Informative Push Notifications
SDK consent acts as a channel-wide gate. When the push consent is not granted, no notifications reach the device, including informative ones such as transaction receipts or service status updates. To deliver informative push to every user while reserving marketing pushes for opted-in users, grant SDK consent unconditionally and segment campaigns on the server through a custom user property.
-
Grant SDK consent unconditionally. Regardless of the user's marketing preference, grant the
pushconsent shown above. This keeps the device eligible to receive any push notification, whether informative or marketing. -
Track the marketing preference as a custom user property. When the user accepts or declines marketing communications in your app, record that decision as a user property such as
marketing_consent:// Android Countly.sharedInstance().userProfile().setProperty("marketing_consent", "true"); Countly.sharedInstance().userProfile().save();Equivalent user-profile methods exist in every Countly SDK. See the User Profile section of the SDK documentation for your platform.
-
Segment campaigns in Countly. Use
marketing_consentas a segmentation filter when creating a push notification:-
Informative campaigns (transactional messages, service updates): no filter on
marketing_consent, so every push-enabled user is reachable. -
Marketing campaigns (promotions, news): filter by
marketing_consent = "true", so only opted-in users receive them.
-
Informative campaigns (transactional messages, service updates): no filter on
Set marketing_consent explicitly for every user during onboarding, even when the user skips the consent prompt. If the property is never recorded, those users may unintentionally pass through marketing filters depending on how the dashboard condition is configured.
Testing Push Notifications
After completing both the server-side credential upload and SDK integration, follow these steps to verify everything is working:
- Run your app on a physical device (push notifications do not work on most simulators/emulators). On iOS, accept the notification permission prompt when it appears.
- Check the Countly Dashboard. Navigate to Push Notifications. You should see at least 1 push-enabled user for your platform. This confirms that the device token was successfully sent to the Countly Server.
- Send a test notification. Click + New Message, select the platform, compose a message, and choose Send to test users. The notification should appear on your test device within seconds.
Test users can be defined in the Countly Dashboard under Management > Applications > Your App > Push Notifications settings. This allows you to send test push notifications to specific devices before targeting your full audience.
Troubleshooting & FAQ
For common issues, error codes, and frequently asked questions about push notifications, see our dedicated troubleshooting page: