Skip to content

App Banner

Ruofan Wei edited this page Sep 16, 2026 · 7 revisions

App Banner integration

App Banner returns the selected banner content as JSON. Your app is responsible for parsing the JSON and rendering the native UI.

Important

App Banner requires OmniSegmentKit 1.1.0 or later and iOS 13 or later.

Before you start

Make sure that:

  • OmniSegmentKit is installed and initialized with your API key and iOS TID.
  • You have received the pageKey and bannerKey configured for the banner.
  • Your app can display the banner's image or video content.

pageKey identifies the current app screen. bannerKey identifies the banner on that screen. Both values must be non-empty and match the values configured in OmniSegment.

The SDK does not create a view or insert content into a WebView.

Banner content

delivery.contentJSON contains the selected banner content as a JSON string.

A card banner can look like this:

{
  "type": "card",
  "card": {
    "image": {
      "enabled": true
    },
    "image_src": [
      {
        "url": "https://cdn.example.com/banner.mp4",
        "type": "video"
      }
    ],
    "title": {
      "enabled": true,
      "text": "Banner title"
    },
    "description": {
      "enabled": true,
      "text": "Banner description"
    },
    "ctaButton": {
      "enabled": true,
      "text": "Learn more"
    },
    "closeButton": {
      "enabled": true
    },
    "redirectUrl": "https://example.com"
  }
}

Use the top-level type to select the banner renderer. The media source in image_src can be either an image or a video:

  • When the media source type is video, render its url with a video player.
  • Otherwise, render the url as an image. Image data may not include a type.
  • Do not load the media when image.enabled is false.
  • Handle media loading failures without blocking the banner's remaining content.
  • Stop and release video playback when the banner or screen is removed.

For each optional block, check enabled before rendering it and handle missing or null values safely. The available fields may vary with the banner configuration, so the app should ignore fields it does not use.

Request and display a banner

The callback is asynchronous and runs on the main thread. Keep the returned request while the screen needs the result. Keep the delivery while the displayed banner can still be clicked or closed.

import OmniSegmentKit

final class HomeViewController: UIViewController {
    private var bannerRequest: OSGBannerRequest?
    private var bannerDelivery: OSGBannerContentDelivery?

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        OmniSegment.setCurrentPage("home")
        loadBanner()
    }

    private func loadBanner() {
        bannerRequest = OmniSegment.requestBannerContent(
            pageKey: "home",
            bannerKey: "home_top"
        ) { [weak self] result in
            guard let self else { return }

            switch result.status {
            case .content:
                guard let delivery = result.delivery else { return }

                renderBanner(from: delivery.contentJSON) { [weak self] in
                    self?.bannerDelivery = delivery
                    delivery.reportDisplayed()
                }

            case .noContent:
                bannerDelivery = nil
                hideBanner()

            case .failed:
                bannerDelivery = nil
                hideBanner()
                handleBannerError(result.error?.code)

            @unknown default:
                bannerDelivery = nil
                hideBanner()
            }
        }
    }

    func bannerWasTapped() {
        bannerDelivery?.reportClicked()
    }

    func bannerWasClosed() {
        bannerDelivery?.reportClosed()
        bannerDelivery = nil
        hideBanner()
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        bannerRequest?.cancel()
        bannerRequest = nil
    }
}

renderBanner, hideBanner, and handleBannerError are placeholders for your app's UI code; they are not SDK methods.

Call reportDisplayed() only after the banner is actually visible. Call reportClicked() and reportClosed() when those actions occur. Each method is safe to call more than once for the same delivery.

Result status

Status delivery error Recommended handling
content Present nil Parse delivery.contentJSON, render the banner, and report its lifecycle events.
noContent nil nil Hide the banner or leave the area empty. This is not an error.
failed nil Present Hide the banner and inspect result.error?.code.

Error codes

Code Meaning
invalidArgument pageKey or bannerKey is empty or contains only whitespace.
notInitialized OmniSegment.initialize has not been called.
network A network request failed.
timedOut The request took too long to complete.
invalidContent The returned content could not be parsed.
internal An unexpected error occurred.

Cancellation

Call cancel() when the screen no longer needs a pending result. A cancelled request does not call its completion handler.

bannerRequest?.cancel()
bannerRequest = nil

Do not cancel the request immediately after creating it.

Objective-C request example

self.bannerRequest = [OmniSegment
    requestBannerContentWithPageKey:@"home"
                          bannerKey:@"home_top"
                          completion:^(OSGBannerContentResult *result) {
    if (result.status == OSGBannerContentStatusContent) {
        OSGBannerContentDelivery *delivery = result.delivery;
        [self renderBannerFromJSON:delivery.contentJSON completion:^{
            self.bannerDelivery = delivery;
            [delivery reportDisplayed];
        }];
    } else if (result.status == OSGBannerContentStatusNoContent) {
        [self hideBanner];
    } else {
        [self handleBannerError:result.error.code];
    }
}];

Clone this wiki locally