
Das AppboyKit (auch bekannt als Objective-C SDK) wird nicht mehr unterstützt und wurde durch das Swift SDK. ] ersetzt. Es wird keine neuen Features, Fehlerbehebungen, Sicherheitsupdates oder technischen Support mehr erhalten - Messaging und Analytics werden jedoch weiterhin wie gewohnt funktionieren. Weitere Informationen finden Sie unter Einführung in das neue Braze Swift SDK.

Suchen Sie nach dem grundlegenden Entwicklerleitfaden zur Integration von Content Cards? Finden Sie ihn im grundlegenden Entwicklerleitfaden zur Integration von Content Cards.
Implementierungsleitfaden für Content Cards
Dieser optionale Leitfaden für die erweiterte Implementierung enthält Hinweise zur Code-Anpassung für Content Cards, drei von unserem Team entwickelte angepasste Anwendungsfälle, begleitende Code-Snippets sowie eine Anleitung zur Protokollierung von Impressionen, Klicks und Ausblendungen. Besuchen Sie unser Braze Demo Repository auf GitHub! Beachten Sie, dass sich dieser Implementierungsleitfaden auf eine Swift-Implementierung konzentriert, aber für Interessierte auch Objective-C-Snippets bereitgestellt werden.
Hinweise zur Code-Anpassung
Content Cards als angepasste Objekte
Ähnlich wie eine Rakete, die einen Booster erhält, können Ihre eigenen angepassten Objekte erweitert werden, um als Content Cards zu fungieren. Begrenzte API-Oberflächen wie diese bieten die Flexibilität, mit verschiedenen Daten-Backends austauschbar zu arbeiten. Dies kann durch die Konformität mit dem ContentCardable-Protokoll und die Implementierung des Initializers (wie in den folgenden Code-Snippets gezeigt) erreicht werden. Durch die Verwendung der ContentCardData-Struktur können Sie auf die ABKContentCard-Daten zugreifen. Die ABKContentCard-Payload wird verwendet, um die ContentCardData-Struktur und das angepasste Objekt selbst zu initialisieren – alles aus einem Dictionary-Typ über den Initializer, den das Protokoll mitbringt.
Der Initializer enthält auch ein ContentCardClassType-Enum. Dieses Enum wird verwendet, um zu entscheiden, welches Objekt initialisiert werden soll. Durch die Verwendung von Schlüssel-Wert-Paaren im Braze-Dashboard können Sie einen expliziten class_type-Schlüssel festlegen, der bestimmt, welches Objekt initialisiert wird. Diese Schlüssel-Wert-Paare für Content Cards werden über die Variable extras auf der ABKContentCard übergeben. Eine weitere zentrale Komponente des Initializers ist der metaData-Dictionary-Parameter. Die metaData enthalten alles aus der ABKContentCard, aufgeteilt in eine Reihe von Schlüsseln und Werten. Nachdem die relevanten Cards geparst und in Ihre angepassten Objekte konvertiert wurden, ist die App bereit, mit ihnen zu arbeiten, als wären sie aus JSON oder einer anderen Quelle instanziiert worden.
Sobald Sie ein solides Verständnis dieser Hinweise zur Code-Anpassung haben, werfen Sie einen Blick auf unsere Anwendungsfälle, um mit der Implementierung Ihrer angepassten Objekte zu beginnen.
ContentCardable-Protokoll
Ein ContentCardData-Objekt, das die ABKContentCard-Daten zusammen mit einem ContentCardClassType-Enum repräsentiert. Ein Initializer, der verwendet wird, um angepasste Objekte mit ABKContentCard-Metadaten zu instanziieren.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protocol ContentCardable {
var contentCardData: ContentCardData? { get }
init?(metaData: [ContentCardKey: Any], classType contentCardClassType: ContentCardClassType)
}
extension ContentCardable {
var isContentCard: Bool {
return contentCardData != nil
}
func logContentCardClicked() {
BrazeManager.shared.logContentCardClicked(idString: contentCardData?.contentCardId)
}
func logContentCardDismissed() {
BrazeManager.shared.logContentCardDismissed(idString: contentCardData?.contentCardId)
}
func logContentCardImpression() {
BrazeManager.shared.logContentCardImpression(idString: contentCardData?.contentCardId)
}
}
Content-Card-Datenstruktur
ContentCardData repräsentiert die geparsten Werte einer ABKContentCard.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct ContentCardData: Hashable {
let contentCardId: String
let contentCardClassType: ContentCardClassType
let createdAt: Double
let isDismissable: Bool
...
// other Content Card properties such as expiresAt, pinned, etc.
}
extension ContentCardData: Equatable {
static func ==(lhs: ContentCardData, rhs: ContentCardData) -> Bool {
return lhs.contentCardId == rhs.contentCardId
}
}
ContentCardable-Protokoll
Ein ContentCardData-Objekt, das die ABKContentCard-Daten zusammen mit einem ContentCardClassType-Enum repräsentiert, ein Initializer, der verwendet wird, um angepasste Objekte mit ABKContentCard-Metadaten zu instanziieren.
1
2
3
4
5
6
7
8
9
10
11
12
@protocol ContentCardable <NSObject>
@property (nonatomic, strong) ContentCardData *contentCardData;
- (instancetype __nullable)initWithMetaData:(NSDictionary *)metaData
classType:(enum ContentCardClassType)classType;
- (BOOL)isContentCard;
- (void)logContentCardImpression;
- (void)logContentCardClicked;
- (void)logContentCardDismissed;
@end
Content-Card-Datenstruktur
ContentCardData repräsentiert die geparsten Werte einer ABKContentCard.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@interface ContentCardData : NSObject
+ (ContentCardClassType)contentCardClassTypeForString:(NSString *)rawValue;
- (instancetype)initWithIdString:(NSString *)idString
classType:(ContentCardClassType)classType
createdAt:(double)createdAt isDismissible:(BOOL)isDismissible;
@property (nonatomic, readonly) NSString *contentCardId;
@property (nonatomic) ContentCardClassType classType;
@property (nonatomic, readonly) double *createdAt;
@property (nonatomic, readonly) BOOL isDismissible;
...
// other Content Card properties such as expiresAt, pinned, etc.
@end
Initializer für angepasste Objekte
Metadaten aus einer ABKContentCard werden verwendet, um die Variablen Ihres Objekts zu befüllen. Die im Braze-Dashboard eingerichteten Schlüssel-Wert-Paare werden im „extras“-Dictionary dargestellt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
extension CustomObject: ContentCardable {
init?(metaData: [ContentCardKey: Any], classType contentCardClassType: ContentCardClassType) {
guard let idString = metaData[.idString] as? String,
let createdAt = metaData[.created] as? Double,
let isDismissable = metaData[.dismissable] as? Bool,
let extras = metaData[.extras] as? [AnyHashable: Any],
else { return nil }
let contentCardData = ContentCardData(contentCardId: idString, contentCardClassType: contentCardClassType, createdAt: createdAt, isDismissable: isDismissable)
let customObjectProperty = extras["YOUR-CUSTOM-OBJECT-PROPERTY"] as? String
self.init(contentCardData: contentCardData, property: customObjectProperty)
}
}
Typen identifizieren
Das ContentCardClassType-Enum repräsentiert den class_type-Wert im Braze-Dashboard. Dieser Wert wird auch als Filter-Bezeichner verwendet, um Content Cards an verschiedenen Stellen anzuzeigen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum ContentCardClassType: Hashable {
case yourValue
case yourOtherValue
...
case none
init(rawType: String?) {
switch rawType?.lowercased() {
case "your_value": // these values much match the value set in the Braze dashboard
self = .yourValue
case "your_other_value": // these values much match the value set in the Braze dashboard
self = .yourOtherValue
...
default:
self = .none
}
}
}
Initializer für angepasste Objekte
Metadaten aus einer ABKContentCard werden verwendet, um die Variablen Ihres Objekts zu befüllen. Die im Braze-Dashboard eingerichteten Schlüssel-Wert-Paare werden im „extras“-Dictionary dargestellt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (id _Nullable)initWithMetaData:(nonnull NSDictionary *)metaData classType:(enum ContentCardClassType)classType {
self = [super init];
if (self) {
if ([metaData objectForKey:ContentCardKeyIdString] && [metaData objectForKey:ContentCardKeyCreated] && [metaData objectForKey:ContentCardKeyDismissible] && [metaData objectForKey:ContentCardKeyExtras]) {
NSDictionary *extras = metaData[ContentCardKeyExtras];
NSString *idString = metaData[ContentCardKeyIdString];
double createdAt = [metaData[ContentCardKeyCreated] doubleValue];
BOOL isDismissible = metaData[ContentCardKeyDismissible];
if ([extras objectForKey: @"YOUR-CUSTOM-PROPERTY")
_customObjectProperty = extras[@"YOUR-CUSTOM-OBJECT-PROPERTY"];
self.contentCardData = [[ContentCardData alloc] initWithIdString:idString classType:classType createdAt:createdAt isDismissible:isDismissible];
return self;
}
}
return nil;
}
Typen identifizieren
Das ContentCardClassType-Enum repräsentiert den class_type-Wert im Braze-Dashboard. Dieser Wert wird auch als Filter-Bezeichner verwendet, um Content Cards an verschiedenen Stellen anzuzeigen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef NS_ENUM(NSInteger, ContentCardClassType) {
ContentCardClassTypeNone = 0,
ContentCardClassTypeYourValue,
ContentCardClassTypeYourOtherValue,
...
};
+ (NSArray *)contentCardClassTypeArray {
return @[ @"", @"your_value", @"your_other_value" ];
}
+ (ContentCardClassType)contentCardClassTypeForString:(NSString*)rawValue {
if ([[self contentCardClassTypeArray] indexOfObject:rawValue] == NSNotFound) {
return ContentCardClassTypeNone;
} else {
NSInteger value = [[self contentCardClassTypeArray] indexOfObject:rawValue];
return (ContentCardClassType) value;
}
}
Content Cards anfordern
Solange der Observer noch im Speicher gehalten wird, kann der Benachrichtigungs-Callback vom Braze SDK erwartet werden.
1
2
3
4
func loadContentCards() {
BrazeManager.shared.addObserverForContentCards(observer: self, selector: #selector(contentCardsUpdated))
BrazeManager.shared.requestContentCardsRefresh()
}
Den Content-Cards-SDK-Callback verarbeiten
Leiten Sie den Benachrichtigungs-Callback an die Hilfsdatei weiter, um die Payload-Daten für Ihre angepassten Objekte zu parsen.
1
2
3
4
5
@objc func contentCardsUpdated(_ notification: Notification) {
guard let contentCards = BrazeManager.shared.handleContentCardsUpdated(notification, for: [.yourValue]) as? [CustomObject],!contentCards.isEmpty else { return }
// do something with your array of custom objects
}
Mit Content Cards arbeiten
Der class_type wird als Filter übergeben, um nur Content Cards zurückzugeben, die einen übereinstimmenden class_type haben.
1
2
3
4
5
func handleContentCardsUpdated(_ notification: Notification, for classTypes: [ContentCardClassType]) -> [ContentCardable] {
guard let updateIsSuccessful = notification.userInfo?[ABKContentCardsProcessedIsSuccessfulKey] as? Bool, updateIsSuccessful, let cards = contentCards else { return [] }
return convertContentCards(cards, for: classTypes)
}
Content Cards anfordern
Solange der Observer noch im Speicher gehalten wird, kann der Benachrichtigungs-Callback vom Braze SDK erwartet werden.
1
2
3
4
- (void)loadContentCards {
[[BrazeManager shared] addObserverForContentCards:self selector:@selector(contentCardsUpdated:)];
[[BrazeManager shared] requestContentCardsRefresh];
}
Den Content-Cards-SDK-Callback verarbeiten
Leiten Sie den Benachrichtigungs-Callback an die Hilfsdatei weiter, um die Payload-Daten für Ihre angepassten Objekte zu parsen.
1
2
3
4
5
6
- (void)contentCardsUpdated:(NSNotification *)notification {
NSArray *classTypes = @[@(ContentCardClassTypeYourValue)];
NSArray *contentCards = [[BrazeManager shared] handleContentCardsUpdated:notification forClassTypes:classTypes];
// do something with your array of custom objects
}
Mit Content Cards arbeiten
Der class_type wird als Filter übergeben, um nur Content Cards zurückzugeben, die einen übereinstimmenden class_type haben.
1
2
3
4
5
6
7
8
- (NSArray *)handleContentCardsUpdated:(NSNotification *)notification forClassType:(ContentCardClassType)classType {
BOOL updateIsSuccessful = [notification.userInfo[ABKContentCardsProcessedIsSuccessfulKey] boolValue];
if (updateIsSuccessful) {
return [self convertContentCards:self.contentCards forClassType:classType];
} else {
return @[];
}
}
Mit Payload-Daten arbeiten
Durchläuft das Array der Content Cards und parst nur die Cards mit einem übereinstimmenden class_type. Die Payload einer ABKContentCard wird in ein Dictionary geparst.
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
func convertContentCards(_ cards: [ABKContentCard], for classTypes: [ContentCardClassType]) -> [ContentCardable] {
var contentCardables: [ContentCardable] = []
for card in cards {
let classTypeString = card.extras?[ContentCardKey.classType.rawValue] as? String
let classType = ContentCardClassType(rawType: classTypeString)
guard classTypes.contains(classType) else { continue }
var metaData: [ContentCardKey: Any] = [:]
switch card {
case let banner as ABKBannerContentCard:
metaData[.image] = banner.image
case let captioned as ABKCaptionedImageContentCard:
metaData[.title] = captioned.title
metaData[.cardDescription] = captioned.cardDescription
metaData[.image] = captioned.image
case let classic as ABKClassicContentCard:
metaData[.title] = classic.title
metaData[.cardDescription] = classic.cardDescription
default:
break
}
metaData[.idString] = card.idString
metaData[.created] = card.created
metaData[.dismissible] = card.dismissible
metaData[.urlString] = card.urlString
metaData[.extras] = card.extras
...
// other Content Card properties such as expiresAt, pinned, etc.
if let contentCardable = contentCardable(with: metaData, for: classType) {
contentCardables.append(contentCardable)
}
}
return contentCardables
}
Ihre angepassten Objekte aus Content-Card-Payload-Daten initialisieren
Der class_type wird verwendet, um zu bestimmen, welches Ihrer angepassten Objekte aus den Payload-Daten initialisiert wird.
1
2
3
4
5
6
7
8
9
10
11
func contentCardable(with metaData: [ContentCardKey: Any], for classType: ContentCardClassType) -> ContentCardable? {
switch classType {
case .yourValue:
return CustomObject(metaData: metaData, classType: classType)
case .yourOtherValue:
return OtherCustomObject(metaData: metaData, classType: classType)
...
default:
return nil
}
}
Mit Payload-Daten arbeiten
Durchläuft das Array der Content Cards und parst nur die Cards mit einem übereinstimmenden class_type. Die Payload einer ABKContentCard wird in ein Dictionary geparst.
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
- (NSArray *)convertContentCards:(NSArray<ABKContentCard*> *)cards forClassType:(ContentCardClassType)classType {
NSMutableArray *contentCardables = [[NSMutableArray alloc] init]; for (ABKContentCard *card in cards) {
NSString *classTypeString = [card.extras objectForKey:ContentCardKeyClassType];
ContentCardClassType cardClassType = [ContentCardData contentCardClassTypeForString: classTypeString];
if (cardClassType != classType) { continue; }
NSMutableDictionary *metaData = [[NSMutableDictionary alloc] init];
if ([card isKindOfClass:[ABKBannerContentCard class]]) {
ABKBannerContentCard *banner = (ABKBannerContentCard *)card;
metaData[ContentCardKeyImage] = banner.image;
} else if ([card isKindOfClass:[ABKCaptionedImageContentCard class]]) {
ABKCaptionedImageContentCard *captioned = (ABKCaptionedImageContentCard *)card;
metaData[ContentCardKeyTitle] = captioned.title;
metaData[ContentCardKeyCardDescription] = captioned.cardDescription;
metaData[ContentCardKeyImage] = captioned.image;
} else if ([card isKindOfClass:[ABKClassicContentCard class]]) {
ABKClassicContentCard *classic = (ABKClassicContentCard *)card;
metaData[ContentCardKeyCardDescription] = classic.title;
metaData[ContentCardKeyImage] = classic.image;
}
metaData[ContentCardKeyIdString] = card.idString;
metaData[ContentCardKeyCreated] = [NSNumber numberWithDouble:card.created];
metaData[ContentCardKeyDismissible] = [NSNumber numberWithBool:card.dismissible];
metaData[ContentCardKeyUrlString] = card.urlString;
metaData[ContentCardKeyExtras] = card.extras;
...
// other Content Card properties such as expiresAt, pinned, etc.
id<ContentCardable> contentCardable = [self contentCardableWithMetaData:metaData forClassType:classType];
if (contentCardable) {
[contentCardables addObject:contentCardable];
}
}
return contentCardables;
}
Ihre angepassten Objekte aus Content-Card-Payload-Daten initialisieren
Der class_type wird verwendet, um zu bestimmen, welches Ihrer angepassten Objekte aus den Payload-Daten initialisiert wird.
1
2
3
4
5
6
7
8
9
10
11
- (id<ContentCardable>)contentCardableWithMetaData:(NSDictionary *)metaData forClassType:(ContentCardClassType)classType {
switch (classType) {
case ContentCardClassTypeYourValue:
return [[CustomObject alloc] initWithMetaData:metaData classType:classType];
case ContentCardClassTypeYourOtherValue:
return nil;
...
default:
return nil;
}
}
Anwendungsfälle
Im folgenden Abschnitt haben wir drei Anwendungsfälle bereitgestellt. Jeder Anwendungsfall bietet eine detaillierte Erklärung, relevante Code-Snippets und einen Einblick, wie Content-Card-Variablen im Braze-Dashboard aussehen und verwendet werden können:
- Content Cards als ergänzende Inhalte
- Content Cards in einem Nachrichtencenter
- Interaktive Content Cards
Content Cards als ergänzende Inhalte

Sie können Content Cards nahtlos in einen bestehenden Feed integrieren, sodass Daten aus mehreren Feeds gleichzeitig geladen werden. Dies schafft ein stimmiges, harmonisches Erlebnis mit Braze Content Cards und bestehenden Feed-Inhalten.
Das begleitende Beispiel zeigt eine UICollectionView mit einer hybriden Liste von Artikeln, die sowohl über lokale Daten als auch über von Braze bereitgestellte Content Cards befüllt werden. Damit können Content Cards nicht von vorhandenen Inhalten unterschieden werden.
Dashboard-Konfiguration
Diese Content-Card wird über eine API-getriggerte Campaign mit API-getriggerten Schlüssel-Wert-Paaren ausgeliefert. Dies ist ideal für Campaigns, bei denen die Werte der Karte von externen Faktoren abhängen, um zu bestimmen, welche Inhalte den Nutzer:innen angezeigt werden. Beachten Sie, dass class_type zum Zeitpunkt der Einrichtung bekannt sein sollte.

Bereit, Analytics zu protokollieren?
Besuchen Sie den folgenden Abschnitt, um ein besseres Verständnis dafür zu bekommen, wie der Datenfluss aussehen sollte.
Content Cards in einem Nachrichtencenter
Content Cards können in einem Nachrichtencenter-Format verwendet werden, bei dem jede Nachricht eine eigene Karte ist. Jede Nachricht im Nachrichtencenter wird über ein Content-Card-Payload befüllt, und jede Karte enthält zusätzliche Schlüssel-Wert-Paare, die das On-Click-UI/UX steuern. Im folgenden Beispiel leitet eine Nachricht Sie zu einer beliebigen angepassten Ansicht weiter, während eine andere ein Webview öffnet, das angepasstes HTML anzeigt.

Dashboard-Konfiguration
Für die folgenden Nachrichtentypen sollte das Schlüssel-Wert-Paar class_type zu Ihrer Dashboard-Konfiguration hinzugefügt werden. Die hier zugewiesenen Werte sind beliebig, sollten sich jedoch zwischen den Klassentypen unterscheiden lassen. Diese Schlüssel-Wert-Paare sind die Schlüsselkennungen, anhand derer die Anwendung entscheidet, wohin navigiert wird, wenn Nutzer:innen auf eine gekürzte Posteingangs-Nachricht klicken.
Die Schlüssel-Wert-Paare für diesen Anwendungsfall umfassen:
message_headergesetzt alsFull Pageclass_typegesetzt alsmessage_full_page

Die Schlüssel-Wert-Paare für diesen Anwendungsfall umfassen:
message_headergesetzt alsHTMLclass_typegesetzt alsmessage_webviewmessage_title
Diese Nachricht sucht ebenfalls nach einem HTML-Schlüssel-Wert-Paar. Wenn Sie jedoch mit einer Web-Domain arbeiten, ist auch ein URL-Schlüssel-Wert-Paar gültig.

Weitere Erläuterung
Die Nachrichtencenter-Logik wird durch den contentCardClassType gesteuert, der über die Schlüssel-Wert-Paare von Braze bereitgestellt wird. Mithilfe der Methode addContentCardToView können Sie diese Klassentypen sowohl filtern als auch identifizieren.
Verwendung von class_type für das On-Click-Verhalten
Wenn eine Nachricht angeklickt wird, bestimmt der ContentCardClassType, wie der nächste Bildschirm befüllt werden soll.
1
2
3
4
5
6
7
8
9
10
func addContentCardToView(with message: Message) {
switch message.contentCardData?.contentCardClassType {
case .message(.fullPage):
loadContentCardFullPageView(with: message as! FullPageMessage)
case .message(.webView):
loadContentCardWebView(with: message as! WebViewMessage)
default:
break
}
}
Verwendung von class_type für das On-Click-Verhalten
Wenn eine Nachricht angeklickt wird, bestimmt der ContentCardClassType, wie der nächste Bildschirm befüllt werden soll.
1
2
3
4
5
6
7
8
9
10
11
12
- (void)addContentCardToView:(Message *)message {
switch (message.contentCardData.classType) {
case ContentCardClassTypeMessageFullPage:
[self loadContentCardFullPageView:(FullPageMessage *)message];
break;
case ContentCardClassTypeMessageWebview:
[self loadContentCardWebView:(WebViewMessage *)message];
break;
default:
break;
}
}
Bereit, Analytics zu protokollieren?
Besuchen Sie den folgenden Abschnitt, um ein besseres Verständnis dafür zu bekommen, wie der Datenfluss aussehen sollte.

Interaktive Content Cards
Content Cards können verwendet werden, um dynamische und interaktive Erlebnisse für Ihre Nutzer:innen zu schaffen. Im begleitenden Beispiel erscheint ein Content-Card-Pop-up beim Checkout, um Nutzer:innen Last-Minute-Aktionen anzubieten.
Gut platzierte Karten wie diese sind eine hervorragende Möglichkeit, Nutzer:innen einen „Anstoß“ in Richtung bestimmter Aktionen zu geben.
Dashboard-Konfiguration
Die Dashboard-Konfiguration für interaktive Content Cards ist unkompliziert. Die Schlüssel-Wert-Paare für diesen Anwendungsfall umfassen einen discount_percentage, der als gewünschter Rabattbetrag festgelegt wird, und einen class_type, der als coupon_code gesetzt wird. Diese Schlüssel-Wert-Paare bestimmen, wie typspezifische Content Cards gefiltert und auf dem Checkout-Bildschirm angezeigt werden.

Bereit, Analytics zu protokollieren?
Besuchen Sie den folgenden Abschnitt, um ein besseres Verständnis dafür zu bekommen, wie der Datenfluss aussehen sollte.
Anpassung des Dark Mode
Standardmäßig reagieren Content-Card-Ansichten automatisch auf Änderungen des Dark Mode auf dem Gerät mit einem Satz thematisch angepasster Farben.
Dieses Verhalten kann wie in unserem Leitfaden für angepasste Stile beschrieben überschrieben werden.
Impressionen, Klicks und Schließungen protokollieren
Nachdem Sie Ihre angepassten Objekte so erweitert haben, dass sie als Content Cards fungieren, können Sie wertvolle Metriken wie Impressionen, Klicks und Schließungen schnell protokollieren. Dies kann über ein ContentCardable-Protokoll erfolgen, das auf eine Hilfsdatei verweist und ihr Daten zur Protokollierung durch das Braze SDK bereitstellt.
Implementierungskomponenten
Analytics protokollieren
Die Protokollierungsmethoden können direkt von Objekten aufgerufen werden, die dem ContentCardable-Protokoll entsprechen.
1
2
3
customObject.logContentCardImpression()
customObject.logContentCardClicked()
customObject.logContentCardDismissed()
Die ABKContentCard abrufen
Der idString, der von Ihrem angepassten Objekt übergeben wird, dient zur Identifizierung der zugehörigen Content Card, um Analytics zu protokollieren.
1
2
3
4
5
6
7
8
9
10
11
extension BrazeManager {
func logContentCardImpression(idString: String?) {
guard let contentCard = getContentCard(forString: idString) else { return }
contentCard.logContentCardImpression()
}
private func getContentCard(forString idString: String?) -> ABKContentCard? {
return contentCards?.first(where: { $0.idString == idString })
}
}
Analytics protokollieren
Die Protokollierungsmethoden können direkt von Objekten aufgerufen werden, die dem ContentCardable-Protokoll entsprechen.
1
2
3
[customObject logContentCardImpression];
[customObject logContentCardClicked];
[customObject logContentCardDismissed];
Die ABKContentCard abrufen
Der idString, der von Ihrem angepassten Objekt übergeben wird, dient zur Identifizierung der zugehörigen Content Card, um Analytics zu protokollieren.
1
2
3
4
5
6
7
8
9
10
11
- (void)logContentCardImpression:(NSString *)idString {
ABKContentCard *contentCard = [self getContentCard:idString];
[contentCard logContentCardImpression];
}
- (ABKContentCard *)getContentCard:(NSString *)idString {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self.idString == %@", idString];
NSArray *filteredArray = [self.contentCards filteredArrayUsingPredicate:predicate];
return filteredArray.firstObject;
}

Für eine Control-Variante einer Content Card sollte dennoch ein angepasstes Objekt instanziiert und die UI-Logik so eingestellt werden, dass die zugehörige Ansicht des Objekts ausgeblendet wird. Das Objekt kann dann eine Impression protokollieren, um unsere Analytics darüber zu informieren, wann Nutzer:innen die Control Card gesehen hätten.
Hilfsdateien
ContentCardKey-Hilfsdatei
1
2
3
4
5
6
7
8
enum ContentCardKey: String {
case idString
case created
case classType = "class_type"
case dismissible
case extras
...
}
1
2
3
4
5
6
static NSString *const ContentCardKeyIdString = @"idString";
static NSString *const ContentCardKeyCreated = @"created";
static NSString *const ContentCardKeyClassType = @"class_type";
static NSString *const ContentCardKeyDismissible = @"dismissible";
static NSString *const ContentCardKeyExtras = @"extras";
...