EVGCampaignHandler Block Reference

Declared in
EVGCampaign.h

Block Definition 

Callback implemented by the app to handle potential custom data campaigns served in response to Marketing Cloud Personalization actions generated by the user interacting with the app.

1typedef void (^EVGCampaignHandler) (EVGCampaign *__nonnull campaign)

For additional information, see Mobile Data Campaigns. For lifecycle details, see [EVGContext setCampaignHandler:forTarget:].

Usage Details:

  • For a view controller, it is recommended to setup handlers in viewWillAppear:, as shown in the examples in this section.
  • Validate the expected campaign data/JSON before processing, since campaigns are dynamic and designed in the Personalization web app.
  • The same campaign could be re-served, so when applicable, check if the same content is already active. For example, there’s no need to re-render the same message/UI to the user if it’s still visible. This is especially true when testing a specific experience, see [Evergage(Swizzling) handleOpenURL:].
  • Follow best practices using weak references within the handler block, to avoid retaining objects in memory longer than expected, which could lead to memory bloat and unexpected behavior. The following examples correctly use weak reference.

The following is example code that expects the featured product’s name and updates a UILabel on screen.

  • Objective-C

    1// In ViewController.m
    2
    3- (void)viewWillAppear:(BOOL)animated {
    4    [super viewWillAppear:animated];
    5
    6    __weak typeof(self) weakSelf = self;
    7    EVGCampaignHandler handler = ^(EVGCampaign * __nonnull campaign) {
    8        // Safest to perform a single method/operation on weakSelf, which will simply be a no-op if weakSelf is nil:
    9        [weakSelf handleCampaign:campaign];
    10    };
    11
    12    // The target string uniquely identifies the expected data schema - here, a featured product:
    13    [self.evergageScreen setCampaignHandler:handler forTarget:@"Featured Product"];
    14}
    15
    16- (void)handleCampaign:(nonnull EVGCampaign *)campaign {
    17    // Validate the campaign data since it's dynamic JSON. Avoid processing if fails.
    18    NSString *featuredProductName = campaign.data[@"featuredProductName"];
    19    if (![featuredProductName isKindOfClass:[NSString class]] || !featuredProductName.length) {
    20        return;
    21    }
    22
    23    // Check if the same content is already visible/active (see Usage Details above).
    24    if (self.activeCampaign && [self.activeCampaign isEqual:campaign]) {
    25        NSLog(@"Ignoring campaign name %@ since equivalent content is already active", campaign.campaignName);
    26        return;
    27    }
    28
    29    // Track the impression for statistics even if the user is in the control group.
    30    [self.evergageScreen trackImpression:campaign];
    31
    32    // Only display the campaign if the user is not in the control group.
    33    if (!campaign.isControlGroup) {
    34        // Keep active campaign as long as needed for (re)display and comparison
    35        self.activeCampaign = campaign;
    36        NSLog(@"New active campaign name %@ for target %@ with data %@",
    37            campaign.campaignName, campaign.target, campaign.data);
    38
    39        // Display campaign content
    40        self.featuredProductLabel.text = [NSString stringWithFormat:@"Our featured product is %@!", featuredProductName];
    41    }
    42}
  • Swift

    1// In ViewController.swift
    2
    3override func viewWillAppear(_ animated: Bool) {
    4    super.viewWillAppear(animated)
    5
    6    // Note self is captured weakly
    7    let handler = { [weak self] (campaign: EVGCampaign) -> Void in
    8        // Safest to perform a single method/operation on weakSelf, which will simply be a no-op if weakSelf is nil:
    9        self?.handleCampaign(campaign: campaign)
    10    }
    11
    12    // The target string uniquely identifies the expected data schema - here, a featured product:
    13    evergageScreen?.setCampaignHandler(handler, forTarget: "Featured Product")
    14}
    15
    16func handleCampaign(campaign: EVGCampaign) {
    17    // Validate the campaign data since it's dynamic JSON. Avoid processing if fails.
    18    guard let featuredProductName = campaign.data["featuredProductName"] as? String
    19        else { return }
    20    if (featuredProductName.isEmpty) { return }
    21
    22    // Check if the same content is already visible/active (see Usage Details above).
    23    if (activeCampaign && activeCampaign.equals(campaign)) {
    24    NSLog("Ignoring campaign name %@ since equivalent content is already active",
    25        campaign.campaignName)
    26        return
    27    }
    28
    29    // Track the impression for statistics even if the user is in the control group.
    30    evergageScreen?.trackImpression(campaign)
    31
    32    // Only display the campaign if the user is not in the control group.
    33    if (!campaign.isControlGroup) {
    34        // Keep active campaign as long as needed for (re)display and comparison
    35        activeCampaign = campaign
    36        NSLog("New active campaign name %@ for target %@ with data %@",
    37            campaign.campaignName, campaign.target, campaign.data)
    38
    39        featuredProductLabel.text = String(format: "Our featured product is %@!", featuredProductName)
    40    }
    41}