AppboyKit (également connu sous le nom de SDK Objective-C) n’est plus pris en charge et a été remplacé par Swift SDK. Il ne recevra plus de nouvelles fonctionnalités, de corrections de bugs, de mises à jour de sécurité ou d’assistance technique - cependant, la messagerie et l’analyse continueront à fonctionner normalement. Pour en savoir plus, consultez Présentation du nouveau SDK Braze Swift.
Vous recherchez le guide d’intégration de base du développeur de notifications push ? Trouvez-le here.
Guide d’implémentation des notifications push
Ce guide d’implémentation avancé et facultatif traite des moyens d’exploiter les extensions d’application de contenu de notification push pour tirer le meilleur parti des messages push. Il contient également trois cas d’usage personnalisés créés par notre équipe, les extraits de code l’accompagnant et des directives concernant l’enregistrement des analyses. Visitez notre dépôt de démonstrations Braze ici! Notez que ce guide d’implémentation est centré autour d’une implémentation Swift, mais les extraits de code Objective-C sont fournis aux personnes intéressées.
Extensions d’application de contenu de notification

Les notifications push, en apparence standard sur différentes plateformes, offrent de très nombreuses options de personnalisation, au-delà de ce qui est normalement implémenté dans l’interface utilisateur par défaut. Lorsqu’une notification push est étendue, les extensions de notification de contenu permettent un affichage personnalisé de la notification push agrandie.
Les notifications push peuvent être étendues de trois manières différentes :
- Un appui long sur la bannière de notification push
- Faire glisser sur la bannière de notification push
- Faire glisser la bannière vers la gauche et sélectionner « View (Visualiser) »
Ces vues personnalisées offrent des moyens astucieux d’engager les clients en vous permettant d’afficher de nombreux types de contenu différents, y compris des notifications interactives, des notifications push incluant des données utilisateur, et même des messages push qui peuvent recueillir des informations telles que les numéros de téléphone et l’e-mail. Bien que la mise en œuvre du push de cette manière puisse être peu familière à certains, l’une de nos fonctionnalités bien connues chez Braze, les Push Stories, sont un excellent exemple de ce à quoi peut ressembler une vue personnalisée pour une extension d’app de contenu de notification !
Conditions

- Les notifications push intégrées avec succès dans votre app.
- iOS 10 ou supérieur
- Les fichiers suivants générés par Xcode en fonction de votre langue de codage :
Swift
NotificationViewController.swiftMainInterface.storyboard
Objectif-CNotificationViewController.hNotificationViewController.mMainInterface.storyboard
Configuration de catégorie personnalisée
Pour configurer un affichage personnalisé dans le tableau de bord, vous devez activer les boutons de notification et saisir votre catégorie personnalisée. La catégorie iOS personnalisée pré-enregistrée que vous fournissez est ensuite vérifiée par rapport à UNNotificationExtensionCategory dans le .plist de votre cible d’extension de contenu de notification. La valeur donnée ici doit correspondre à ce qui est défini dans le tableau de bord de Braze.

Étant donné que les notifications push avec des extensions de contenu ne sont pas toujours apparentes, il est recommandé d’inclure un appel à l’action pour inciter vos utilisateurs à développer leurs notifications push.
Cas d’utilisation et guide d’implémentation
Trois types d’extensions d’application de contenu de notification push sont fournis. Chaque type a une conception conceptuelle, des cas d’utilisation potentiels et un aperçu de la façon dont les variables de notification push peuvent ressembler et être utilisées dans le tableau de bord de Braze :
- Notification push interactive
- Notifications push personnalisées
- Notifications push pour le recueil d’informations
Notification push interactive
Les notifications push peuvent répondre aux actions de l’utilisateur dans une extension de contenu. Pour les utilisateurs exécutant iOS 12 ou une version ultérieure, cela signifie que vous pouvez transformer vos messages push en notifications push entièrement interactives ! Cette interactivité offre de nombreuses possibilités pour impliquer vos utilisateurs au travers de vos notifications. L’exemple suivant montre une notification push dans laquelle les utilisateurs peuvent participer à un jeu sous forme de match une fois la notification étendue.

Configuration du tableau de bord
Pour configurer une vue personnalisée dans le tableau de bord, dans les paramètres du bouton de notification, entrez la catégorie spécifique que vous souhaitez afficher. Ensuite, dans la .plist de votre extension de contenu de notification, vous devez également définir la catégorie personnalisée dans l’attribut UNNotificationExtensionCategory. La valeur donnée ici doit correspondre à ce qui est défini dans le tableau de bord de Braze. Enfin, pour activer les interactions utilisateur dans une notification push, définissez la clé UNNotificationExtensionInteractionEnabled sur « true ».


Autres cas d’utilisation
Les extensions de contenu de notifications push sont une option intéressante pour introduire de l’interactivité dans vos promotions et vos applications. Certains exemples incluent un jeu auquel les utilisateurs peuvent jouer, une roue pour gagner des réductions ou un bouton « J’aime » pour enregistrer une liste ou une chanson.
Prêt à enregistrer l’analyse ?
Consultez la section suivante pour mieux comprendre à quoi doit ressembler le flux de données.
Notifications push personnalisées

Les notifications push peuvent afficher des informations spécifiques à l’utilisateur dans une extension de contenu. L’exemple à droite montre une notification push après qu’un utilisateur a terminé une tâche spécifique (cours d’apprentissage de Braze) et est maintenant encouragé à développer cette notification pour vérifier ses progrès. Les informations fournies ici sont spécifiques à l’utilisateur et peuvent être lancées à la fin de la session ou après une action spécifique de l’utilisateur en tirant parti d’un déclencheur API.
Configuration du tableau de bord
Pour configurer un push personnalisé dans le tableau de bord, vous devez enregistrer la catégorie spécifique que vous souhaitez voir s’afficher, puis, dans les paires clé-valeur à l’aide de Liquid standard, définir les attributs utilisateur appropriés que vous souhaitez voir apparaître dans le message. Ces vues peuvent être personnalisées sur la base des attributs utilisateur spécifiques d’un profil utilisateur donné.

Gérer les paires clé-valeur
La méthode suivante, didReceive est appelée lorsque l’extension de contenu a reçu une notification, elle est disponible dans le NotificationViewController. Les paires clé-valeur fournies dans le tableau de bord sont représentées dans le code par l’utilisation d’un dictionnaire userInfo.
Analyser des paires clé-valeur à partir de notifications push
1
2
3
4
5
6
7
8
9
func didReceive(_ notification: UNNotification) {
let userInfo = notification.request.content.userInfo
guard let value = userInfo["YOUR-KEY-VALUE-PAIR"] as? String,
let otherValue = userInfo["YOUR-OTHER-KEY-VALUE-PAIR"] as? String,
else { fatalError("Key-Value Pairs are incorrect.")}
...
}
1
2
3
4
5
6
7
8
9
10
11
- (void)didReceiveNotification:(nonnull UNNotification *)notification {
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[@"YOUR-KEY-VALUE-PAIR"] && userInfo[@"YOUR-OTHER-KEY-VALUE-PAIR"]) {
...
} else {
[NSException raise:NSGenericException format:@"Key-Value Pairs are incorrect"];
}
}
Autres cas d’utilisation
Les idées d’extensions de contenu push basées sur la progression et axées utilisateur sont infinies, certains exemples incluent l’ajout de l’option de partage de votre progression sur différentes plateformes, l’expression de réalisations débloquées, de cartes perforées ou même de listes de contrôle d’intégration.
Prêt à enregistrer l’analyse ?
Consultez la section suivante pour mieux comprendre à quoi doit ressembler le flux de données.
Notification push de recueil d’informations
Les notifications push peuvent capturer des informations utilisateur à l’intérieur d’une extension de contenu, ce qui vous permet de repousser les limites de ce qui est possible avec une notification push. En examinant le flux suivant illustré, la vue est en mesure de répondre aux changements d’état. Ces composants de changement d’état sont représentés dans chaque image.
- L’utilisateur reçoit une notification push.
- La notification push est ouverte et invite l’utilisateur à communiquer des informations.
- Des informations sont fournies et, si elles sont valides, le bouton d’enregistrement s’affiche.
- La vue de confirmation s’affiche et la notification push est rejetée.

Notez que les informations demandées ici peuvent être très variables, comme le recueil de numéros de SMS par ex., et ne doivent pas forcément être en relation avec l’e-mail.
Configuration du tableau de bord
Pour configurer une notification push de capture d’information dans le tableau de bord, vous devez enregistrer et définir votre catégorie personnalisée et fournir les paires clé-valeur nécessaires. Comme illustré par l’exemple, vous pouvez également inclure une image dans votre notification push. Pour ce faire, vous devez intégrer les notifications riches, définir le style de notification de votre campagne sur Notification riche et inclure une image push riche.

Gérer les actions des boutons
Chaque bouton d’action est identifié de manière unique. Le code vérifie si votre identifiant de réponse est égal à actionIndentifier, et, si c’est le cas, sait que l’utilisateur a cliqué sur le bouton d’action.
Gestion des réponses aux boutons d’action des notifications push
1
2
3
4
5
6
7
func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
if response.actionIdentifier == "YOUR-REGISTER-IDENTIFIER" {
// do something
} else {
// do something else
}
}
1
2
3
4
5
6
7
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption))completion {
if ([response.actionIdentifier isEqualToString:@"YOUR-REGISTER-IDENTIFIER"]) {
completion(UNNotificationContentExtensionResponseOptionDismiss);
} else {
completion(UNNotificationContentExtensionResponseOptionDoNotDismiss);
}
}
Rejet des notifications push
Les notifications push peuvent être automatiquement rejetées en appuyant sur un bouton d’action. Il existe trois options de rejet des notifications push prédéfinies recommandées :
completion(.dismiss)- Rejet de la notificationcompletion(.doNotDismiss)- La notification reste ouvertecompletion(.dismissAndForward)- La notification push est rejetée et l’utilisateur est redirigé vers l’application.
Autres cas d’utilisation
Demander la contribution des utilisateurs via des notifications push est une formidable opportunité dont de nombreuses entreprises ne profitent pas. Dans ces messages push, vous pouvez non seulement demander des informations de base comme le nom, l’adresse e-mail ou le numéro, mais vous pouvez également inviter les utilisateurs à compléter un profil d’utilisateur s’il ne l’est pas déjà, ou même à soumettre des commentaires.
Prêt à enregistrer l’analyse ?
Consultez la section suivante pour mieux comprendre à quoi doit ressembler le flux de données.
Enregistrer les analyses
Enregistrer avec l’API Braze (recommandé)
L’enregistrement des analyses peut uniquement se faire en temps réel avec l’aide du serveur du client qui utilise notre endpoint /users/track. Pour enregistrer l’analyse, envoyez la valeur braze_id dans le champ des paires clé-valeur (comme indiqué dans la capture d’écran suivante) pour identifier le profil utilisateur à mettre à jour.

Enregistrement manuel
La journalisation manuelle exigera la configuration préalable des groupes d’applications dans Xcode, puis la création, l’enregistrement et la récupération des analyses. Cela nécessitera un travail de développeur personnalisé de votre côté. Les extraits de code suivants vous aideront à résoudre ce problème.
Il est également important de noter que les analyses ne seront pas envoyées à Braze tant que l’application mobile n’aura pas été lancée subséquemment. Cela signifie que, selon vos paramètres de rejet, il existe souvent une période indéterminée entre le moment où une notification push est rejetée et l’application mobile est lancée et que les analyses sont récupérées. Bien que cette période tampon n’affecte pas tous les cas d’utilisation, les utilisateurs doivent prendre en compte l’impact et, si nécessaire, ajuster leur parcours utilisateur pour inclure l’ouverture de l’application pour répondre à ce problème.

Étape 1 : Configurer les groupes d’applications dans Xcode
Ajouter une capacité App Groups. Si vous n’avez pas de groupe d’applications dans votre application, allez sur Capacité de la cible de l’application principale, activez App Groups, et cliquez sur le bouton « + ». Utilisez l’ID de l’ensemble de votre application pour créer le groupe d’applications. Par exemple, si l’ID de l’ensemble de votre application est com.company.appname, vous pouvez nommer votre groupe d’applications group.com.company.appname.xyz. Assurez-vous que les App Groups sont activés pour la cible de votre application principale et la cible de l’extension de contenu.

Étape 2 : Intégrer les extraits de code
Les extraits de code suivants sont une référence utile sur la façon d’enregistrer et d’envoyer des événements personnalisés, des attributs personnalisés et des attributs utilisateur. Ce guide sera en cours de conversation par défaut d’utilisateur, mais la représentation du code sera sous la forme d’un fichier d’aide RemoteStorage. Il existe également des fichiers auxiliaires supplémentaires UserAttributes et EventName Dictionary utilisés lors de l’envoi et de l’enregistrement des attributs utilisateur. Tous les fichiers d’aide sont disponibles à la fin de ce guide.
Enregistrement des événements personnalisés
Pour enregistrer des événements personnalisés, vous devez créer l’analyse à partir de zéro. Pour ce faire, créez un dictionnaire, renseignez-le avec des métadonnées et enregistrez les données via l’utilisation d’un fichier d’aide.
- Initialiser un dictionnaire avec des métadonnées d’événement
- Initialiser
userDefaultspour récupérer et stocker les données d’événements - Si un tableau existe déjà, ajoutez-y de nouvelles données et enregistrez
- S’il n’y a pas de tableau existant, enregistrez le nouveau tableau sur
userDefaults
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func saveCustomEvent(with properties: [String: Any]? = nil) {
// 1
let customEventDictionary = Dictionary(eventName: "YOUR-EVENT-NAME", properties: properties)
// 2
let remoteStorage = RemoteStorage(storageType: .suite)
// 3
if var pendingEvents = remoteStorage.retrieve(forKey: .pendingCustomEvents) as? [[String: Any]] {
pendingEvents.append(contentsOf: [customEventDictionary])
remoteStorage.store(pendingEvents, forKey: .pendingCustomEvents)
} else {
// 4
remoteStorage.store([customEventDictionary], forKey: .pendingCustomEvents)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)saveCustomEvent:(NSDictionary<NSString *, id> *)properties {
// 1
NSDictionary<NSString *, id> *customEventDictionary = [[NSDictionary alloc] initWithEventName:@"YOUR-EVENT-NAME" properties:properties];
// 2
RemoteStorage *remoteStorage = [[RemoteStorage alloc] initWithStorageType:StorageTypeSuite];
NSMutableArray *pendingEvents = [[remoteStorage retrieveForKey:RemoteStorageKeyPendingCustomEvents] mutableCopy];
// 3
if (pendingEvents) {
[pendingEvents addObject:customEventDictionary];
[remoteStorage store:pendingEvents forKey:RemoteStorageKeyPendingCustomAttributes];
} else {
// 4
[remoteStorage store:@[ customEventDictionary ] forKey:RemoteStorageKeyPendingCustomAttributes];
}
}
Envoi d’événements personnalisés à Braze
Une fois le SDK initialisé, c’est le bon moment pour consigner toutes les analyses enregistrées à partir d’une extension d’application de contenu de notification. Pour ce faire, vous pouvez parcourir tous les événements en attente, en vérifiant la clé « Event Name », en définissant les valeurs appropriées dans Braze, puis en effaçant l’enregistrement pour la prochaine fois que cette fonction sera nécessaire.
- Passez en revue la série d’événements en attente
- Passez en revue chaque paire clé-valeur dans le dictionnaire
pendingEvents - En vérifiant explicitement la clé pour « Event Name » afin de définir la valeur en conséquence
- Toutes les autres clés-valeurs seront ajoutées au dictionnaire
properties - Consigner un événement personnalisé individuel
- Supprimer tous les événements en attente du stockage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func logPendingCustomEventsIfNecessary() {
let remoteStorage = RemoteStorage(storageType: .suite)
guard let pendingEvents = remoteStorage.retrieve(forKey: .pendingCustomEvents) as? [[String: Any]] else { return }
// 1
for event in pendingEvents {
var eventName: String?
var properties: [AnyHashable: Any] = [:]
// 2
for (key, value) in event {
if key == PushNotificationKey.eventName.rawValue {
// 3
if let eventNameValue = value as? String {
eventName = eventNameValue
} else {
print("Invalid type for event_name key")
}
} else {
// 4
properties[key] = value
}
}
// 5
if let eventName = eventName {
logCustomEvent(eventName, withProperties: properties)
}
}
// 6
remoteStorage.removeObject(forKey: .pendingCustomEvents)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- (void)logPendingEventsIfNecessary {
RemoteStorage *remoteStorage = [[RemoteStorage alloc] initWithStorageType:StorageTypeSuite];
NSArray *pendingEvents = [remoteStorage retrieveForKey:RemoteStorageKeyPendingCustomEvents];
// 1
for (NSDictionary<NSString *, id> *event in pendingEvents) {
NSString *eventName = nil;
NSMutableDictionary *properties = [NSMutableDictionary dictionary];
// 2
for (NSString* key in event) {
if ([key isEqualToString:@"event_name"]) {
// 3
if ([[event objectForKey:key] isKindOfClass:[NSString class]]) {
eventName = [event objectForKey:key];
} else {
NSLog(@"Invalid type for event_name key");
}
} else {
// 4
properties[key] = event[key];
}
}
// 5
if (eventName != nil) {
[[Appboy sharednstance] logCustomEvent:eventName withProperties:properties];
}
}
// 6
[remoteStorage removeObjectForKey:RemoteStorageKeyPendingCustomEvents];
}
Enregistrer des attributs personnalisés
Pour enregistrer des attributs personnalisés, vous devez créer l’analyse à partir de zéro. Pour ce faire, créez un dictionnaire, renseignez-le avec des métadonnées et enregistrez les données via l’utilisation d’un fichier d’aide.
- Initialiser un dictionnaire avec des attributs de métadonnées
- Initialiser
userDefaultspour récupérer et stocker les données d’attributs - Si un tableau existe déjà, ajoutez-y de nouvelles données et enregistrez
- S’il n’y a pas de tableau existant, enregistrez le nouveau tableau sur
userDefaults
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func saveCustomAttribute() {
// 1
let customAttributeDictionary: [String: Any] = ["YOUR-CUSTOM-ATTRIBUTE-KEY": "YOUR-CUSTOM-ATTRIBUTE-VALUE"]
// 2
let remoteStorage = RemoteStorage(storageType: .suite)
// 3
if var pendingAttributes = remoteStorage.retrieve(forKey: .pendingCustomAttributes) as? [[String: Any]] {
pendingAttributes.append(contentsOf: [customAttributeDictionary])
remoteStorage.store(pendingAttributes, forKey: .pendingCustomAttributes)
} else {
// 4
remoteStorage.store([customAttributeDictionary], forKey: .pendingCustomAttributes)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)saveCustomAttribute {
// 1
NSDictionary<NSString *, id> *customAttributeDictionary = @{ @"YOUR-CUSTOM-ATTRIBUTE-KEY": @"YOUR-CUSTOM-ATTRIBUTE-VALUE" };
// 2
RemoteStorage *remoteStorage = [[RemoteStorage alloc] initWithStorageType:StorageTypeSuite];
NSMutableArray *pendingAttributes = [[remoteStorage retrieveForKey:RemoteStorageKeyPendingCustomAttributes] mutableCopy];
// 3
if (pendingAttributes) {
[pendingAttributes addObject:customAttributeDictionary];
[remoteStorage store:pendingAttributes forKey:RemoteStorageKeyPendingCustomAttributes];
} else {
// 4
[remoteStorage store:@[ customAttributeDictionary ] forKey:RemoteStorageKeyPendingCustomAttributes];
}
}
Envoyer des attributs personnalisés à Braze
Une fois le SDK initialisé, c’est le bon moment pour consigner toutes les analyses enregistrées à partir d’une extension d’application de contenu de notification. Pour ce faire, vous pouvez parcourir tous les attributs en attente, en définissant l’attribut personnalisé approprié dans Braze, puis en effaçant l’enregistrement pour la prochaine fois que cette fonction sera nécessaire.
- Passez en revue la série d’attributs en attente
- Passez en revue chaque paire clé-valeur dans le dictionnaire
pendingAttributes - Enregistrer l’attribut personnalisé individuel avec la clé et la valeur correspondantes
- Supprimer tous les attributs en attente du stockage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func logPendingCustomAttributesIfNecessary() {
let remoteStorage = RemoteStorage(storageType: .suite)
guard let pendingAttributes = remoteStorage.retrieve(forKey: .pendingCustomAttributes) as? [[String: Any]] else { return }
// 1
pendingAttributes.forEach { setCustomAttributesWith(keysAndValues: $0) }
// 4
remoteStorage.removeObject(forKey: .pendingCustomAttributes)
}
func setCustomAttributesWith(keysAndValues: [String: Any]) {
// 2
for (key, value) in keysAndValues {
// 3
if let value = value as? [String] {
setCustomAttributeArrayWithKey(key, andValue: value)
} else {
setCustomAttributeWithKey(key, andValue: value)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (void)logPendingCustomAttributesIfNecessary {
RemoteStorage *remoteStorage = [[RemoteStorage alloc] initWithStorageType:StorageTypeSuite];
NSArray *pendingAttributes = [remoteStorage retrieveForKey:RemoteStorageKeyPendingCustomAttributes];
// 1
for (NSDictionary<NSString*, id> *attribute in pendingAttributes) {
[self setCustomAttributeWith:attribute];
}
// 4
[remoteStorage removeObjectForKey:RemoteStorageKeyPendingCustomAttributes];
}
- (void)setCustomAttributeWith:(NSDictionary<NSString *, id> *)keysAndValues {
// 2
for (NSString *key in keysAndValues) {
// 3
[self setCustomAttributeWith:key andValue:[keysAndValues objectForKey:key]];
}
}
Enregistrer des attributs utilisateur
Lors de l’enregistrement des attributs utilisateur, il est recommandé de créer un objet personnalisé pour déchiffrer le type d’attribut en cours de mise à jour (email, first_name, phone_number, etc.). L’objet doit être compatible avec ce qui a été stocké/récupéré dans UserDefaults. Voir le fichier d’aide UserAttribute pour un exemple de la manière d’y parvenir.
- Initialiser un objet
UserAttributeencodé avec le type correspondant - Initialiser
userDefaultspour récupérer et stocker les données d’événements - Si un tableau existe déjà, ajoutez-y de nouvelles données et enregistrez
- S’il n’y a pas de tableau existant, enregistrez le nouveau tableau sur
userDefaults
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func saveUserAttribute() {
// 1
guard let data = try? PropertyListEncoder().encode(UserAttribute.userAttributeType("USER-ATTRIBUTE-VALUE")) else { return }
// 2
let remoteStorage = RemoteStorage(storageType: .suite)
// 3
if var pendingAttributes = remoteStorage.retrieve(forKey: .pendingUserAttributes) as? [Data] {
pendingAttributes.append(contentsOf: [data])
remoteStorage.store(pendingAttributes, forKey: .pendingUserAttributes)
} else {
// 4
remoteStorage.store([data], forKey: .pendingUserAttributes)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (void)saveUserAttribute {
// 1
UserAttribute *userAttribute = [[UserAttribute alloc] initWithUserField:@"USER-ATTRIBUTE-VALUE" attributeType:UserAttributeTypeEmail];
NSError *error;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:userAttribute requiringSecureCoding:YES error:&error];
if (error != nil) {
// log error
}
// 2
RemoteStorage *remoteStorage = [[RemoteStorage alloc] initWithStorageType:StorageTypeSuite];
NSMutableArray *pendingAttributes = [[remoteStorage retrieveForKey:RemoteStorageKeyPendingUserAttributes] mutableCopy];
// 3
if (pendingAttributes) {
[pendingAttributes addObject:data];
[remoteStorage store:pendingAttributes forKey:RemoteStorageKeyPendingUserAttributes];
} else {
// 4
[remoteStorage store:@[data] forKey:RemoteStorageKeyPendingUserAttributes];
}
}
Envoyer des attributs utilisateur à Braze
Une fois le SDK initialisé, c’est le bon moment pour consigner toutes les analyses enregistrées à partir d’une extension d’application de contenu de notification. Pour ce faire, vous pouvez parcourir tous les attributs en attente, en définissant l’attribut personnalisé approprié dans Braze, puis en effaçant l’enregistrement pour la prochaine fois que cette fonction sera nécessaire.
- Parcourir le tableau de données
pendingAttributes - Initialiser un objet
UserAttributeencodé à partir des données d’attribut - Définir un champ utilisateur spécifique basé sur le type d’attribut utilisateur (e-mail)
- Supprimer tous les attributs utilisateur en attente du stockage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func logPendingUserAttributesIfNecessary() {
let remoteStorage = RemoteStorage(storageType: .suite)
guard let pendingAttributes = remoteStorage.retrieve(forKey: .pendingUserAttributes) as? [Data] else { return }
// 1
for attributeData in pendingAttributes {
// 2
guard let userAttribute = try? PropertyListDecoder().decode(UserAttribute.self, from: attributeData) else { continue }
// 3
switch userAttribute {
case .email(let email):
user?.email = email
}
}
// 4
remoteStorage.removeObject(forKey: .pendingUserAttributes)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (void)logPendingUserAttributesIfNecessary {
RemoteStorage *remoteStorage = [[RemoteStorage alloc] initWithStorageType:StorageTypeSuite];
NSArray *pendingAttributes = [remoteStorage retrieveForKey:RemoteStorageKeyPendingUserAttributes];
// 1
for (NSData *attributeData in pendingAttributes) {
NSError *error;
// 2
UserAttribute *userAttribute = [NSKeyedUnarchiver unarchivedObjectOfClass:[UserAttribute class] fromData:attributeData error:&error];
if (error != nil) {
// log error
}
// 3
if (userAttribute) {
switch (userAttribute.attributeType) {
case UserAttributeTypeEmail:
[self user].email = userAttribute.userField;
break;
}
}
}
// 4
[remoteStorage removeObjectForKey:RemoteStorageKeyPendingUserAttributes];
}
Fichiers d’aide
RemoteStorage Helper File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
enum RemoteStorageKey: String, CaseIterable {
// MARK: - Notification Content Extension Analytics
case pendingCustomEvents = "pending_custom_events"
case pendingCustomAttributes = "pending_custom_attributes"
case pendingUserAttributes = "pending_user_attributes"
}
enum RemoteStorageType {
case standard
case suite
}
class RemoteStorage: NSObject {
private var storageType: RemoteStorageType = .standard
private lazy var defaults: UserDefaults = {
switch storageType {
case .standard:
return .standard
case .suite:
return UserDefaults(suiteName: "YOUR-DOMAIN-IDENTIFIER")!
}
}()
init(storageType: RemoteStorageType = .standard) {
self.storageType = storageType
}
func store(_ value: Any, forKey key: RemoteStorageKey) {
defaults.set(value, forKey: key.rawValue)
}
func retrieve(forKey key: RemoteStorageKey) -> Any? {
return defaults.object(forKey: key.rawValue)
}
func removeObject(forKey key: RemoteStorageKey) {
defaults.removeObject(forKey: key.rawValue)
}
func resetStorageKeys() {
for key in RemoteStorageKey.allCases {
defaults.removeObject(forKey: key.rawValue)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@interface RemoteStorage ()
@property (nonatomic) StorageType storageType;
@property (nonatomic, strong) NSUserDefaults *defaults;
@end
@implementation RemoteStorage
- (id)initWithStorageType:(StorageType)storageType {
if (self = [super init]) {
self.storageType = storageType;
}
return self;
}
- (void)store:(id)value forKey:(RemoteStorageKey)key {
[[self defaults] setValue:value forKey:[self rawValueForKey:key]];
}
- (id)retrieveForKey:(RemoteStorageKey)key {
return [[self defaults] objectForKey:[self rawValueForKey:key]];
}
- (void)removeObjectForKey:(RemoteStorageKey)key {
[[self defaults] removeObjectForKey:[self rawValueForKey:key]];
}
- (void)resetStorageKeys {
[[self defaults] removeObjectForKey:[self rawValueForKey:RemoteStorageKeyPendingCustomEvents]];
[[self defaults] removeObjectForKey:[self rawValueForKey:RemoteStorageKeyPendingCustomAttributes]];
[[self defaults] removeObjectForKey:[self rawValueForKey:RemoteStorageKeyPendingUserAttributes]];
}
- (NSUserDefaults *)defaults {
if (!self.defaults) {
switch (self.storageType) {
case StorageTypeStandard:
return [NSUserDefaults standardUserDefaults];
break;
case StorageTypeSuite:
return [[NSUserDefaults alloc] initWithSuiteName:@"YOUR-DOMAIN-IDENTIFIER"];
}
} else {
return self.defaults;
}
}
- (NSString*)rawValueForKey:(RemoteStorageKey)remoteStorageKey {
switch(remoteStorageKey) {
case RemoteStorageKeyPendingCustomEvents:
return @"pending_custom_events";
case RemoteStorageKeyPendingCustomAttributes:
return @"pending_custom_attributes";
case RemoteStorageKeyPendingUserAttributes:
return @"pending_user_attributes";
default:
[NSException raise:NSGenericException format:@"Unexpected FormatType."];
}
}
UserAttribute Helper File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
enum UserAttribute: Hashable {
case email(String?)
}
// MARK: - Codable
extension UserAttribute: Codable {
private enum CodingKeys: String, CodingKey {
case email
}
func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .email(let email):
try values.encode(email, forKey: .email)
}
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let email = try values.decode(String.self, forKey: .email)
self = .email(email)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@implementation UserAttribute
- (id)initWithUserField:(NSString *)userField attributeType:(UserAttributeType)attributeType {
if (self = [super init]) {
self.userField = userField;
self.attributeType = attributeType;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.userField forKey:@"userField"];
[encoder encodeInteger:self.attributeType forKey:@"attributeType"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.userField = [decoder decodeObjectForKey:@"userField"];
NSInteger attributeRawValue = [decoder decodeIntegerForKey:@"attributeType"];
self.attributeType = (UserAttributeType) attributeRawValue;
}
return self;
}
@end
EventName Dictionary Helper File
1
2
3
4
5
6
7
8
9
10
11
12
extension Dictionary where Key == String, Value == Any {
init(eventName: String, properties: [String: Any]? = nil) {
self.init()
self[PushNotificationKey.eventName.rawValue] = eventName
if let properties = properties {
for (key, value) in properties {
self[key] = value
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@implementation NSDictionary (Helper)
- (id)initWithEventName:(NSString *)eventName properties:(NSDictionary *)properties {
self = [self init];
if (self) {
dict[@"event_name"] = eventName;
for(id key in properties) {
dict[key] = properties[key];
}
}
return self;
}
@end
Modifier cette page sur GitHub