Push-Analytics und Protokollierung angepasster Events
Diese Seite behandelt die folgenden Workflows: native Push-Analytics (Öffnungen, beeinflusste Öffnungen und Campaign-Reporting) sowie die Protokollierung angepasster Daten (angepasste Events und Attribute) aus Push-Payloads. Nutzen Sie diesen Leitfaden, um festzustellen, welcher Workflow für Ihren Anwendungsfall gilt, und folgen Sie den Schritten für Ihre Plattform.
Voraussetzungen
Bevor Sie beginnen, schließen Sie die anfängliche Push-Benachrichtigungs-Integration für Ihre Plattform ab:
Native Push-Analytics vs. angepasste Event-Protokollierung
Die folgenden Workflows haben jeweils unterschiedliche Reporting-Oberflächen.
| Analytics-Kategorie | Beschreibung | Wo sie erscheint |
|---|---|---|
| Native Push-Analytics | Push-Metriken wie Öffnungen und beeinflusste Öffnungen, die mit Braze-Push-Campaigns verknüpft sind | Push-Campaign-Analytics, Currents-Nachrichten-Engagement-Events, Berichts-Builder |
| Angepasste Events und Attribute | Analytics, die Sie über SDK-Methoden oder den /users/track-Endpunkt definieren und protokollieren |
Nutzer:innenprofile, Segmentierung, aktionsbasierte Campaigns und Canvases, angepasste Event-Analytics |

Das Protokollieren eines angepassten Events (z. B. push_notification_opened) ist nicht dasselbe wie das native Braze-Push-Öffnungs-Tracking. Angepasste Events füllen weder die nativen Push-Campaign-Öffnungsmetriken noch die Push-Attribution.
Was Braze automatisch protokolliert
Wenn Ihre SDK-Integration konfiguriert ist, protokolliert Braze automatisch die wichtigsten Interaktionsdaten des Kanals, einschließlich Push-Öffnungen und beeinflusster Öffnungen. Für die Standard-Push-Analytics ist kein zusätzlicher Code erforderlich. Eine vollständige Liste der automatisch erfassten Daten finden Sie unter SDK-Datenerfassung.
Weitere Informationen finden Sie hier:
- SDK-Datenerfassung für eine vollständige Liste der automatisch erfassten und optionalen Daten.
- Beeinflusste Öffnungen für Informationen darüber, wie Braze beeinflusste Öffnungen berechnet.
- Nachrichten-Engagement-Events für nachgelagerte Event-Schemata in Currents.
Native Push-Analytics mit angepasster Push-Verarbeitung beibehalten
Möglicherweise verwenden Sie einen angepassten Push-Handler, wenn Sie mehrere Push-Anbieter integrieren, zusätzliche Payload-Daten verarbeiten oder eine benutzerdefinierte Benachrichtigungsanzeige-Logik implementieren müssen. Wenn Sie einen angepassten Push-Handler verwenden, müssen Sie Push-Payloads dennoch an die Braze SDK-Methoden übergeben. Dadurch kann Braze die eingebetteten Tracking-Daten extrahieren und native Push-Analytics protokollieren (Öffnungen, beeinflusste Öffnungen und Zustellungsmetriken).
Wenn Sie einen angepassten FirebaseMessagingService verwenden, rufen Sie BrazeFirebaseMessagingService.handleBrazeRemoteMessage(...) innerhalb Ihrer onMessageReceived-Methode auf. Beachten Sie, dass Ihre FirebaseMessagingService-Unterklasse die Ausführung innerhalb von 9 Sekunden nach dem Aufruf abschließen muss, um nicht vom Android-System markiert oder beendet zu werden.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (BrazeFirebaseMessagingService.handleBrazeRemoteMessage(this, remoteMessage)) {
// Braze processed a Braze push payload.
} else {
// Non-Braze payload: pass to your other handlers.
}
}
}
Ein vollständiges Implementierungsbeispiel finden Sie in der Braze Android SDK Firebase-Push-Beispiel-App.
Bei einer manuellen Push-Integration leiten Sie Hintergrund- und Nutzer:innen-Benachrichtigungs-Callbacks an Braze weiter.
Hintergrund-Benachrichtigungen:
if let braze = AppDelegate.braze, braze.notifications.handleBackgroundNotification(
userInfo: userInfo,
fetchCompletionHandler: completionHandler
) {
return
}
completionHandler(.noData)
Antworten auf Nutzer:innen-Benachrichtigungen:
if let braze = AppDelegate.braze, braze.notifications.handleUserNotification(
response: response,
withCompletionHandler: completionHandler
) {
return
}
completionHandler()
Vordergrund-Benachrichtigungen:
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
if let braze = AppDelegate.braze {
braze.notifications.handleForegroundNotification(notification: notification)
}
if #available(iOS 14.0, *) {
completionHandler([.banner, .list, .sound])
} else {
completionHandler([.alert, .sound])
}
}
Ein vollständiges Implementierungsbeispiel finden Sie im Braze Swift SDK – manuelles Push-Beispiel (AppDelegate.swift).
Konfigurieren Sie für Web-Push Ihren Service Worker und die SDK-Initialisierung wie unter Web-Push-Benachrichtigungen beschrieben.
Weitere Code-Beispiele finden Sie im Braze Web SDK Repository.
Angepasste Daten aus Push-Payloads protokollieren
Verwenden Sie diesen Abschnitt, wenn Sie zusätzliche Daten aus Push-Payload-Schlüssel-Wert-Paaren protokollieren müssen, z. B. angepasste Events oder Attribute, die mit Ihrer Geschäftslogik verknüpft sind.
Weitere Informationen zu angepassten Events finden Sie unter Angepasste Events. Informationen zum Protokollieren angepasster Events über SDK-Methoden finden Sie unter Angepasste Events protokollieren.
Option A: Mit dem /users/track-Endpunkt protokollieren
Sie können Analytics in Echtzeit protokollieren, indem Sie den /users/track-Endpunkt aufrufen.
Um das Nutzerprofil zu identifizieren, fügen Sie braze_id in Ihre Push-Payload-Schlüssel-Wert-Paare ein.

Die Übergabe von braze_id identifiziert nur das Profil. Sie benötigen weiterhin Implementierungslogik, die Payload-Werte liest und die /users/track-Anfrage mit den Events oder Attributen sendet, die Sie protokollieren möchten.
Option B: Nach dem App-Start mit SDK-Methoden protokollieren
Sie können Payload-Daten auch lokal speichern und angepasste Events und Attribute nach der Initialisierung der App über SDK-Methoden protokollieren. Dieser Ansatz ist in Notification-Content-Extension-Flows üblich, bei denen Analytics-Daten zuerst gespeichert und beim nächsten App-Start gesendet werden.

Analytics werden erst an Braze gesendet, wenn die App gestartet wird. Je nach Ihren Einstellungen zum Schließen von Benachrichtigungen kann es zu einer Verzögerung zwischen dem Zeitpunkt kommen, an dem Nutzer:innen die Benachrichtigung schließen, und dem Zeitpunkt, an dem die App geöffnet wird und die Analytics sendet.
Protokollierung aus einer Notification Content Extension (Swift)
Die folgenden Schritte beschreiben, wie Sie angepasste Events, angepasste Attribute und Nutzer:innen-Attribute aus einer Swift Notification Content Extension speichern und senden.
Schritt 1: App-Gruppen in Xcode konfigurieren
Fügen Sie in Xcode die Funktion App Groups zu Ihrem Haupt-App-Target hinzu. Aktivieren Sie App Groups und klicken Sie dann auf +, um eine neue Gruppe hinzuzufügen. Verwenden Sie die Bundle-ID Ihrer App, um den Gruppenbezeichner zu erstellen (zum Beispiel group.com.company.appname.xyz). Aktivieren Sie App Groups sowohl für Ihr Haupt-App-Target als auch für das Content-Extension-Target.

Schritt 2: Festlegen, was protokolliert werden soll
Bevor Sie die Snippets implementieren, wählen Sie die Analytics-Kategorie, die Sie protokollieren möchten:
- Angepasste Events: Aktionen, die Nutzer:innen ausführen (zum Beispiel einen Flow abschließen oder auf ein bestimmtes UI-Element tippen). Verwenden Sie angepasste Events für aktionsbasierte Trigger, Segmentierung und Event-Analytics. Weitere Informationen finden Sie unter Angepasste Events und Angepasste Events protokollieren.
- Angepasste Attribute: Profilfelder, die Sie definieren (zum Beispiel
plan_tieroderpreferred_language) und im Laufe der Zeit aktualisieren. Weitere Informationen finden Sie unter Angepasste Attribute und Nutzer:innen-Attribute festlegen. - Nutzer:innen-Attribute: Standard-Profilfelder (zum Beispiel E-Mail, Vorname und Telefonnummer). Im Beispielcode werden diese durch ein typisiertes
UserAttribute-Modell dargestellt und dann den Braze-Nutzer:innen-Feldern zugeordnet.
Die Hilfsdateien in diesem Abschnitt (RemoteStorage, UserAttribute und EventName Dictionary) sind lokale Hilfsdateien, die von dieser Beispielimplementierung verwendet werden. Sie sind keine integrierten SDK-Klassen. Sie speichern aus der Payload abgeleitete Daten in UserDefaults, definieren ein typisiertes Modell für ausstehende Nutzer:innen-Updates und standardisieren den Aufbau der Event-Payload. Weitere Informationen zum lokalen Datenspeicherverhalten finden Sie unter Speicher.

Die Beispiele für Hilfsdateien in diesem Abschnitt sind iOS-spezifisch (Swift und Objective-C). Informationen zu Android- und Web-Ansätzen für die Protokollierung angepasster Events und Attribute finden Sie unter Angepasste Events protokollieren (Android, Web) und Nutzer:innen-Attribute festlegen (Android, Web).
Angepasste Events speichern
Erstellen Sie die Analytics-Payload, indem Sie ein Dictionary aufbauen, Metadaten befüllen und es mit der Hilfsdatei speichern.
- Initialisieren Sie ein Dictionary mit Event-Metadaten.
- Initialisieren Sie
userDefaults, um Event-Daten abzurufen und zu speichern. - Wenn ein vorhandenes Array gefunden wird, hängen Sie an und speichern Sie.
- Wenn kein Array existiert, speichern Sie ein neues Array.
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)
}
}
- (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:RemoteStorageKeyPendingCustomEvents];
} else {
// 4
[remoteStorage store:@[ customEventDictionary ] forKey:RemoteStorageKeyPendingCustomEvents];
}
}
Angepasste Events an Braze senden
Protokollieren Sie gespeicherte Analytics direkt nach der SDK-Initialisierung.
- Iterieren Sie durch die ausstehenden Events.
- Iterieren Sie durch die Schlüssel-Wert-Paare in jedem Event.
- Prüfen Sie auf den Schlüssel
event_name. - Fügen Sie die verbleibenden Schlüssel-Wert-Paare zum
properties-Dictionary hinzu. - Protokollieren Sie jedes angepasste Event.
- Entfernen Sie die ausstehenden Events aus dem Speicher.
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 == "event_name" {
// 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 {
AppDelegate.braze?.logCustomEvent(name: eventName, properties: properties)
}
}
// 6
remoteStorage.removeObject(forKey: .pendingCustomEvents)
}
- (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) {
[AppDelegate.braze logCustomEvent:eventName properties:properties];
}
}
// 6
[remoteStorage removeObjectForKey:RemoteStorageKeyPendingCustomEvents];
}
Angepasste Attribute speichern
Erstellen Sie das Analytics-Dictionary als neues Design und persistieren Sie es anschließend.
- Initialisieren Sie ein Dictionary mit Attribut-Metadaten.
- Initialisieren Sie
userDefaults, um Attribut-Daten abzurufen und zu speichern. - Wenn ein vorhandenes Array gefunden wird, hängen Sie an und speichern Sie.
- Wenn kein Array existiert, speichern Sie ein neues Array.
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)
}
}
- (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];
}
}
Angepasste Attribute an Braze senden
Protokollieren Sie gespeicherte Analytics direkt nach der SDK-Initialisierung.
- Iterieren Sie durch die ausstehenden Attribute.
- Iterieren Sie durch jedes Schlüssel-Wert-Paar.
- Protokollieren Sie jeden angepassten Attribut-Schlüssel und -Wert.
- Entfernen Sie die ausstehenden Attribute aus dem Speicher.
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)
}
}
}
- (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]];
}
}
Nutzer:innen-Attribute speichern
Erstellen Sie beim Speichern von Nutzer:innen-Attributen ein angepasstes Objekt, das erfasst, welches Nutzer:innen-Feld aktualisiert wird (email, first_name, phone_number usw.). Das Objekt sollte mit dem Speichern und Abrufen über UserDefaults kompatibel sein. Ein Beispiel finden Sie in der UserAttribute-Hilfsdatei im Tab Hilfsdateien.
- Initialisieren Sie ein codiertes
UserAttribute-Objekt mit dem entsprechenden Typ. - Initialisieren Sie
userDefaults, um die Daten abzurufen und zu speichern. - Wenn ein vorhandenes Array gefunden wird, hängen Sie an und speichern Sie.
- Wenn kein Array existiert, speichern Sie ein neues Array.
func saveUserAttribute() {
// 1
guard let data = try? PropertyListEncoder().encode(UserAttribute.email("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)
}
}
- (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];
}
}
Nutzer:innen-Attribute an Braze senden
Protokollieren Sie gespeicherte Analytics direkt nach der SDK-Initialisierung.
- Iterieren Sie durch die
pendingAttributes-Daten. - Decodieren Sie jedes
UserAttribute. - Setzen Sie Nutzer:innen-Felder basierend auf dem Attribut-Typ.
- Entfernen Sie die ausstehenden Nutzer:innen-Attribute aus dem Speicher.
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):
AppDelegate.braze?.user.set(email: email)
}
}
// 4
remoteStorage.removeObject(forKey: .pendingUserAttributes)
}
- (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];
}
RemoteStorage-Hilfsdatei
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:
// Use the App Group identifier you created in Step 1.
return UserDefaults(suiteName: "group.com.company.appname.xyz")!
}
}()
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)
}
}
}
@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 (!_defaults) {
switch (self.storageType) {
case StorageTypeStandard:
_defaults = [NSUserDefaults standardUserDefaults];
break;
case StorageTypeSuite:
_defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.company.appname.xyz"];
break;
}
}
return _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-Hilfsdatei
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.encodeIfPresent(email, forKey: .email)
}
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let email = try values.decodeIfPresent(String.self, forKey: .email)
self = .email(email)
}
}
@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-Hilfsdatei
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
}
}
}
}
@implementation NSMutableDictionary (Helper)
+ (instancetype)dictionaryWithEventName:(NSString *)eventName
properties:(NSDictionary *)properties {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"event_name"] = eventName;
if (properties) {
for (id key in properties) {
dict[key] = properties[key];
}
}
return dict;
}
@end
Ergebnisse analysieren
Verwenden Sie die Berichtsoberfläche, die zur jeweiligen Analytics-Kategorie passt:
| Analytics-Kategorie | Wo in Braze anzeigen |
|---|---|
| Native Push-Analytics | Um Push-Öffnungsmetriken auf Campaign-Ebene anzuzeigen, navigieren Sie zur Seite Campaign Analytics Ihrer Push-Campaign. Metrikdefinitionen finden Sie unter Beeinflusste Öffnungen. Um benutzerdefinierte Analytics-Ansichten zu erstellen, navigieren Sie zu Analytics > Berichts-Builder (Neu). Die Navigationsschritte finden Sie unter Berichts-Builder. Für Event-Schemas auf Warehouse-Ebene siehe Nachricht-Engagement-Events. |
| Angepasste Events und Attribute | Um Trends angepasster Events anzuzeigen, navigieren Sie zu Analytics > Bericht über angepasste Events. Details finden Sie unter Angepasste Events. Um Werte auf Nutzer:innen-Ebene zu prüfen, navigieren Sie zur Seite Nutzer:innen suchen und öffnen Sie ein Profil. Die Schritte finden Sie unter Nutzer:innenprofile. Um Zielgruppen nach diesen Werten zu filtern, navigieren Sie zu Zielgruppe > Segments. Die Navigationsschritte finden Sie unter Segment erstellen sowie die Filteroptionen unter Segmentierungsfilter. |
Informationen zur Erstellung benutzerdefinierter Berichte finden Sie unter Berichts-Builder.