Skip to content

Managing Banner placements

Learn how to create and manage Banner placements in the Braze SDK, including accessing their unique properties and logging impressions. For more general information, see About Banners.

About placement requests

When you create placements in your app or website, your app sends a request to Braze to fetch Banner messages for each placement.

  • You can request up to 10 placements per user session.
  • For each placement, Braze returns the highest-priority Banner the user is eligible to receive.
  • If more than 10 placements are requested in a session, only the first 10 are returned; the rest are dropped.

For example, an app might request three placements during a single session: homepage_promo, cart_abandonment, and seasonal_offer. Each request returns the most relevant Banner for that placement.

Creating a placement

Prerequisites

These are the minimum SDK versions needed to create Banner placements:

Step 1: Create placements in Braze

If you haven’t already, you’ll need to create Banner placements in Braze that are used to define the locations in your app or site can display Banners. To create a placement, go to Settings > Banners Placements, then select Create Placement.

Banner Placements section to create placement IDs.

Give your placement a name and assign a Placement ID. Be sure you consult other teams before assigning an ID, as it’ll be used throughout the card’s lifecycle and shouldn’t be changed later. For more information, see Placement IDs.

Placement details that designate a Banner will display in the left sidebar for spring sale promotion campaigns.

Step 2: Refresh placements in your app

Placements can be requested once per session and will be cached automatically when a user’s session expires or when you change identified users using the changeUser method. The SDK will not re-fetch placements if you call the refresh method again during the same session. Instead, it will log an error and return an error message to the caller.

1
2
3
import * as braze from "@braze/web-sdk";

braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
AppDelegate.braze?.banners.requestRefresh(placementIds: ["global_banner", "navigation_square_banner"])
1
2
3
4
ArrayList<String> listOfBanners = new ArrayList<>();
listOfBanners.add("global_banner");
listOfBanners.add("navigation_square_banner");
Braze.getInstance(context).requestBannersRefresh(listOfBanners);
1
Braze.getInstance(context).requestBannersRefresh(listOf("global_banner", "navigation_square_banner"))
1
Braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
This feature is not currently supported on Unity.
1
This feature is not currently supported on Cordova.
1
braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
This feature is not currently supported on Roku.

Step 3: Listen for updates

1
2
3
4
5
6
7
8
import * as braze from "@braze/web-sdk";

braze.subscribeToBannersUpdates((banners) => {
  console.log(`Banners were updated`);
});

// always refresh after your subscriber function has been registered
braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
2
3
4
5
let cancellable = brazeClient.braze()?.banners.subscribeToUpdates { banners in
  banners.forEach { placementId, banner in
    print("Received banner: \(banner) with placement ID: \(placementId)")
  }
}
1
2
3
4
5
Braze.getInstance(context).subscribeToBannersUpdates(banners -> {
  for (Banner banner : banners.getBanners()) {
    Log.d(TAG, "Received banner: " + banner.getPlacementId());
  }
});
1
2
3
4
5
Braze.getInstance(context).subscribeToBannersUpdates { update ->
  for (banner in update.banners) {
    Log.d(TAG, "Received banner: " + banner.placementId)
  }
}
1
2
3
4
5
6
7
8
9
10
const bannerCardsSubscription = Braze.addListener(
  Braze.Events.BANNER_CARDS_UPDATED,
  (data) => {
    const banners = data.banners;
    console.log(
      `Received ${banners.length} Banner Cards with placement IDs:`,
      banners.map((banner) => banner.placementId)
    );
  }
);
1
This feature is not currently supported on Unity.
1
This feature is not currently supported on Cordova.
1
2
3
4
5
StreamSubscription bannerStreamSubscription = braze.subscribeToBanners((List<BrazeBanner> banners) {
  for (final banner in banners) {
    print("Received banner: " + banner.toString());
  }
});
1
This feature is not currently supported on Roku.

Step 4: Insert using the placement ID

Create a container element for the Banner. Be sure to set its width and height.

1
<div id="global-banner-container" style="width: 100%; height: 450px;"></div>

If you’re using vanilla JavaScript with the Web Braze SDK, call the insertBanner method to replace the inner HTML of the container element.

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
import * as braze from "@braze/web-sdk";

braze.initialize("sdk-api-key", {
  baseUrl: "sdk-base-url",
  allowUserSuppliedJavascript: true, // banners require you to opt-in to user-supplied javascript
});

braze.subscribeToBannersUpdates((banners) => {
  // get this placement's banner. If it's `null` the user did not qualify for one.
  const globalBanner = braze.getBanner("global_banner");
  if (!globalBanner) {
    return;
  }

  // choose where in the DOM you want to insert the banner HTML
  const container = document.getElementById("global-banner-container");

  // Insert the banner which replaces the innerHTML of that container
  braze.insertBanner(globalBanner, container);

  // Special handling if the user is part of a Control Variant
  if (globalBanner.isControl) {
    // hide or collapse the container
    container.style.display = "none";
  }
});

braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);

If you’re using React with the Web Braze SDK, call the insertBanner method with a ref to replace the inner HTML of the container element.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { useRef } from 'react';
import * as braze from "@braze/web-sdk";

export default function App() {
    const bannerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
       const globalBanner = braze.getBanner("global_banner");
       if (!globalBanner || globalBanner.isControl) {
           // hide the container
       } else {
           // insert the banner to the container node
           braze.insertBanner(globalBanner, bannerRef.current);
       }
    }, []);
    return <div ref={bannerRef}></div>
}
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
// To get access to the Banner model object:
let globalBanner: Braze.Banner?
AppDelegate.braze?.banners.getBanner(for: "global_banner", { banner in
  self.globalBanner = banner
})

// If you simply want the Banner view, you may initialize a `UIView` with the placement ID:
if let braze = AppDelegate.braze {
  let bannerUIView = BrazeBannerUI.BannerUIView(
    placementId: "global_banner",
    braze: braze,
    // iOS does not perform automatic resizing or visibility changes.
    // Use the `processContentUpdates` parameter to adjust the size and visibility of your Banner according to your use case.
    processContentUpdates: { result in
      switch result {
      case .success(let updates):
        if let height = updates.height {
          // Adjust the visibility and/or height.
        }
      case .failure(let error):
        // Handle the error.
      }
    }
  )
}

// Similarly, if you want a Banner view in SwiftUI, use the corresponding `BannerView` initializer:
if let braze = AppDelegate.braze {
  let bannerView = BrazeBannerUI.BannerView(
    placementId: "global_banner",
    braze: braze,
    // iOS does not perform automatic resizing or visibility changes.
    // Use the `processContentUpdates` parameter to adjust the size and visibility of your Banner according to your use case.
    processContentUpdates: { result in
      switch result {
      case .success(let updates):
        if let height = updates.height {
          // Adjust the visibility and/or height according to your parent controller.
        }
      case .failure(let error):
        // Handle the error.
      }
    }
  )
}

To get the Banner in Java code, use:

1
Banner globalBanner = Braze.getInstance(context).getBanner("global_banner");

You can create Banners in your Android views layout by including this XML:

1
2
3
4
5
<com.braze.ui.banners.BannerView
    android:id="@+id/global_banner_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:placementId="global_banner" />

If you’re using Android Views, use this XML:

1
2
3
4
5
<com.braze.ui.banners.BannerView
    android:id="@+id/global_banner_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:placementId="global_banner" />

If you’re using Jetpack Compose, you can use this:

1
Banner(placementId = "global_banner")

To get the Banner in Kotlin, use:

1
val banner = Braze.getInstance(context).getBanner("global_banner")

If you’re using React Native’s New Architecture, you need to register BrazeBannerView as a Fabric component in your AppDelegate.mm.

1
2
3
4
5
6
7
8
#ifdef RCT_NEW_ARCH_ENABLED
/// Register the `BrazeBannerView` for use as a Fabric component.
- (NSDictionary<NSString *,Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents {
  NSMutableDictionary * dictionary = [super thirdPartyFabricComponents].mutableCopy;
  dictionary[@"BrazeBannerView"] = [BrazeBannerView class];
  return dictionary;
}
#endif

For the simplest integration, add the following JavaScript XML (JSX) snippet into your view hierarchy, providing just the placement ID.

1
2
3
<Braze.BrazeBannerView
  placementID='global_banner'
/>

To get the Banner’s data model in React Native, or to check for the presence of that placement in your user’s cache, use:

1
const banner = await Braze.getBanner("global_banner");
1
This feature is not currently supported on Unity.
1
This feature is not currently supported on Cordova.

For the simplest integration, add the following widget into your view hierarchy, providing just the placement ID.

1
2
3
4
BrazeBannerView(
  placementId: "global_banner",
),
To get the Banner's data model in Flutter, use:

You can use the getBanner method to check for the presence of that placement in your user’s cache.

1
2
3
4
5
6
7
braze.getBanner("global_banner").then((banner) {
  if (banner == null) {
    // Handle null cases.
  } else {
    print(banner.toString());
  }
});
1
This feature is not currently supported on Roku.

Step 5: Send a test Banner (optional)

Before you launch a Banner campaign, you can send a test Banner to verify your integration. Test Banners will be stored in a separate in-memory cache and won’t persist across app restarts. While no extra setup is needed, your test device must be capable of receiving foreground push notifications so it can display the test.

Logging impressions

Braze automatically logs impressions when you use SDK methods to insert a Banner—so no need to track impressions manually.

Dimensions and sizing

Here’s what you need to know about Banner dimensions and sizing:

  • While the composer allows you to preview Banners in different dimensions, that information isn’t saved or sent to the SDK.
  • The HTML will take up the full width of the container it’s rendered in.
  • We recommend making a fixed dimension element and testing those dimensions in composer.

Custom properties

You can use custom properties from your Banner campaign to retrieve key–value data through the SDK and modify your app’s behavior or appearance. For example, you could:

  • Send metadata for your third-party analytics or integrations.
  • Use metadata such as a timestamp or JSON object to trigger conditional logic.
  • Control the behavior of a banner based on included metadate like ratio or format.

Prerequisites

You’ll need to add custom properties to your Banner campaign. Additionally, these are the minimum SDK versions required to access custom properties:

Accessing custom properties

To access a banner’s custom properties, use one of the following methods based on the property’s type defined in the dashboard. If the key doesn’t match a property of that type, the method returns null.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Returns the Banner instance
const banner = braze.getBanner("placement_id_homepage_top");

// Returns the string property
const stringProperty = banner.getStringProperty("color");

// Returns the boolean property
const booleanProperty = banner.getBooleanProperty("expanded");

// Returns the number property
const numberProperty = banner.getNumberProperty("height");

// Returns the timestamp property (as a Number)
const timestampProperty = banner.getTimestampProperty("account_start");

// Returns the image URL property as a String of the URL
const imageProperty = banner.getImageProperty("homepage_icon");

// Returns the JSON object property as an object in form of JsonPropertyValue
const jsonObjectProperty = banner.getJsonProperty("footer_settings");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Passes the specified banner to the completion handler
AppDelegate.braze?.banners.getBanner(for: "placement_id_homepage_top") { banner in
  // Returns the string property
  let stringProperty: String? = banner.stringProperty(key: "color")

  // Returns the boolean property
  let booleanProperty: Bool? = banner.boolProperty(key: "expanded")

  // Returns the number property as a double
  let numberProperty: Double? = banner.numberProperty(key: "height")

  // Returns the Unix UTC millisecond timestamp property as an integer
  let timestampProperty: Int? = banner.timestampProperty(key: "account_start")

  // Returns the image property as a String of the image URL
  let imageProperty: String? = banner.imageProperty(key: "homepage_icon")

  // Returns the JSON object property as a [String: Any] dictionary
  let jsonObjectProperty: [String: Any]? = banner.jsonObjectProperty(key: "footer_settings")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Returns the Banner instance
Banner banner = Braze.getInstance(context).getBanner("placement_id_homepage_top");

// Returns the string property
String stringProperty = banner.getStringProperty("color");

// Returns the boolean property
Boolean booleanProperty = banner.getBooleanProperty("expanded");

// Returns the number property
Number numberProperty = banner.getNumberProperty("height");

// Returns the timestamp property (as a Long)
Long timestampProperty = banner.getTimestampProperty("account_start");

// Returns the image URL property as a String of the URL
String imageProperty = banner.getImageProperty("homepage_icon");

// Returns the JSON object property as a JSONObject
JSONObject jsonObjectProperty = banner.getJSONProperty("footer_settings");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Returns the Banner instance
val banner: Banner = Braze.getInstance(context).getBanner("placement_id_homepage_top") ?: return

// Returns the string property
val stringProperty: String? = banner.getStringProperty("color")

// Returns the boolean property
val booleanProperty: Boolean? = banner.getBooleanProperty("expanded")

// Returns the number property
val numberProperty: Number? = banner.getNumberProperty("height")

// Returns the timestamp property (as a Long)
val timestampProperty: Long? = banner.getTimestampProperty("account_start")

// Returns the image URL property as a String of the URL
val imageProperty: String? = banner.getImageProperty("homepage_icon")

// Returns the JSON object property as a JSONObject
val jsonObjectProperty: JSONObject? = banner.getJSONProperty("footer_settings")
HOW HELPFUL WAS THIS PAGE?
New Stuff!