In most cases, process of sending a message involves 2 steps:
- Preparation, that is calculation of audience and extracting their language preferences.
- Creation. That is taking a prepared message and creating schedule job .
When using API rather than Countly Dashboard, (1) and (2) can be done in background, so only request (2) is required. But in any case, (1) and (2) will be performed.
This request performs step (2). It creates message and sets it's status to "Created". It also creates a schedule a job for this message which is run right away for non-timezoned messages. If message is about to be sent in users' timezones, it's scheduled 24 hours prior to sending date to ensure users won't move between timezones.
Note that while most of arguments are cross-platform, there are still some differences between iOS & Android platforms which need to be addressed.
Returned JSON contains full message object. Note that Countly supports sending messages to multiple apps at once and even to multiple platforms at once.
Message status
Countly message status (result.status
key) is a bitmap of following statuses:
Number | Status |
---|---|
0 (0) | NotCreated |
1 (1 << 0) | Created - have been created, but haven't been scheduled yet |
2 (1 << 1) | Scheduled - put into sending queue, will be sent on scheduled date |
4 (1 << 2) | Sending - being sent right now |
8 (1 << 3) | Done - done with any processing |
16 (1 << 4) | Error - some error happened during sending |
32 (1 << 5) | Success - sending is completed with some success |
1024 (1 << 10) | Aborted - processing was aborted and won't be repeated due to non-recoverable error (usually credentials error) |
2048 (1 << 11) | Deleted - message was deleted |
Note that statuses above are often combined. For example standard message waiting to be sent within an hour will have status 3 (1 << 0 | 1 << 1). Message which was aborted, but had some successful sends will have status 1081.
Usual way of status transitions is following:
NotCreated => Created => Created | Scheduled => Created | Scheduled | Sending => Created | Done | Success => Created | Done | Success | Deleted
Message result
Result is a JSON object containing results of message sending process:
{
"status": 7,
"total": 23812,
"processed": 123,
"sent": 120,
"error": "Some error string if any",
"resourceErrors": [{"date": 123912313123, "error": "error string"}],
"aborts": [{"date": 123912313123, "error": "error string"}],
}
- total number represents total number of recipients found for this message;
- processed number shows number of notifications sent to APN or GCM service;
- sent number represents number of notifications accepted by APN or GCM (tokens are valid);
- error appears only when all retries spent or unrecoverable error happened;
- resourseErrors appear as message is being sent, mostly connectivity issues are listed here;
- aborts contains unrecoverable errors.
Message localisation
To localise your messages, you need to supply correct messagePerLocale property:
{
"default": "Default message",
"default|p": {
"0": {
"f": "our wonderful user",
"c": true,
"k": "name"
}
},
"default|t": "Default message title",
"default|0|t": "Default button 0 title",
"default|0|l": "http://default.button0.link.com",
"default|1|t": "Default button 1 title",
"default|1|l": "http://default.button1.link.com",
"en": "Message in English",
"en|p": {
"0": {
"f": "our wonderful English-speaking user",
"c": true,
"k": "name"
}
},
"de": "... in Deutsch",
"ru": "... на Русском",
"ru|t": "Заголовок сообщения на Русском",
"en|1|t": "Button 1 title in English"}
}
Correct messagePerLocale object must have "default" message and a message per each locale you want your message to be localized in.
Note complex keys in messagePerLocale:
- LOCALE|p stands for message personalisation object.
- LOCALE|t stands for message title.
- LOCALE|tp stands for message title personalisation object.
- LOCALE|0|t stands for button 0 title.
- LOCALE|0|l stands for button 0 link.
- LOCALE|1|t stands for button 1 title.
- LOCALE|1|l stands for button 1 link.
Button attribute consists of locale name followed by separator (vertical line |, not L letter), then button index (0 or 1), separator again, then either t for title or l (this time lower L) for link.
No need to specify all properties for all locales. Just set default locale and override values for locale you have localisation for. For example set all button titles and links in default locale and only override button titles in languages you support.
Locales are 2-character codes from ISO 639-1 taken from corresponding iOS & Android APIs with exception of all Chinese-language locales (China, Taiwan, etc.) which have only two codes: "zh_hans" for Simplified Chinese and "zh_hant" for Traditional Chinese.
Note that locale parameter is just a helper for Countly Dashboard which contains percentages (from 0.0 to 1.0) for all message texts specified in messagePerLocale for this message (when the message was created). Example message above has locale property saying that 90% of message recipients have English language on their devices, while other 10% of users have other locales and Countly will send default message to them. This distribution is acquired from /i/pushes/prepare method.
Message personalisation
You can make messages dynamic by inserting personalised content into your messages. For example, user's first name or company name. Any property from a user profile can be used for message personalisation. Personalisation object is a key-value pair where key ("0" in example above) is a place in a corresponding string (index) of where to insert user profile property value, and value is an object with 3 mandatory keys: "k" is property key in user profile, "c" is a boolean defining whether to capitalise first letter of the property value, "f" is a fallback value to use when no such property exists in a user profile.
Message sounds
Behaviour of sound property is not cross-platform unless you pay attention to your app implementation:
- On iOS, sound is what it should be - just a sound property in message JSON, see Apple documentation: Preparing Custom Alert Sounds.
- On Android, sound must be a
Uri
pointing at corresponding sound file with an exception of"default"
value which falls back to default sound of notification -Notification.DEFAULT_SOUND
.
Message segmentation
userConditions
& drillConditions
limit audience of a particular message to users with some user properties or behaviour. For example, to send a message to a set of device ids, you can use:
{... "userConditions": {"did": {"$in": ["did1", "did2", ...]}} ...}
To send to users with some custom property set from SDKs:
{... "userConditions": {"custom.propName": {"$in": ["v1", "v2", ...]}} ...}
userConditions
is a standard MongoDB query, while drillConditions
is a specialised drill query. Easiest way to determine a query for a particular use case would be using Chrome Developer Tools to record a request made from Countly dashboard to Countly server.
Transactional messages
Introduced in 18.08 transactional messages allow reusing the same message again and again by just adding users to it with a separate API call. This message must be first created by running this API call (/create) with tx
property set to true. See corresponding API method description for details.