Skip to main content

Regular SDK

Introduction

This page will explain the necessary steps an app developer will have to implement in order to display Outbrain recommendations via a “regular widget” (non-Smartfeed) in their app.

Before reading this guide, please make sure to follow the steps in Getting Started

Guidelines and Limitations

The recommendations that Outbrain provides are time-sensitive. Recommendations are intended for specific users at specific times, and any caching or delay in their presentation will have a negative impact on their performance (and the user experience). The following limitations and guidelines must be applied to the Outbrain recommendations’ display:

  • Storing/caching recommendations with the intent of delaying their presentation on the page is prohibited.
  • Co-mingling of Outbrain recommendations with other content links within the same container is prohibited, unless mutually agreed upon between the client and Outbrain.
  • Altering or replacing an Outbrain recommendation’s text or image is prohibited.
  • All paid recommendations must be uniquely labeled in a manner that can be reasonably associated with the relevant content, as mutually agreed upon between the client and Outbrain.

Widget Overview

While a user is viewing a page on your mobile app, you can display content recommendations that may be interesting to him or her. You can recommend both related content within your own app, and 3rd-party content recommendations. You can choose how and when to display the recommendations, whether as a footer, in-feed or other format.

The image below illustrates how a user might view Outbrain recommendations:

TODO

The Outbrain Workflow

The Outbrain workflow consists of the following main actions:

  • Request content recommendations related to a specific article or app location.
  • Receive a list of recommendations
  • Display the recommendations on the screen.
  • When a user clicks on a recommendation, navigate to the recommendation.

A widget is a UI component, implemented within the app. When you design your app, you decide which widgets will display Outbrain recommendations and respond to clicks on them.

For each widget displaying Outbrain recommendations, you must consult with your Outbrain account manager and decide on a suitable configuration. The configuration refers to settings such as:

  • The number of recommendations to be displayed in the widget
  • Whether thumbnail images should be displayed for each recommendation
  • Whether to recommend articles or videos

Once these settings are determined, your account manager assigns a unique ID for each different widget configuration. This is the value you pass in the widgetId parameter when calling fetchRecommendations().

Requesting Recommendations

When you want to request content recommendations, call Outbrain’s fetchRecommendationsForRequest method. Outbrain will send a response containing a collection of recommendations, based on the request parameters and the Outbrain configuration.

fetchRecommendationsForRequest takes an OBRequest parameter. This is an instance of OBRequest, containing the request details (see OBRequest Properties).

In addition, when calling fetchRecommendationsForRequest, you must supply either a callback handler (OBResponseCompletionHandler) or a delegate (OBResponseDelegate), to handle the recommendations response. (See Handling and Displaying Recommendations to learn more about handling the response.)

Here is an example of how to call fetchRecommendationsForRequest:

let request = OBRequest(url: url, widgetID: "SDK_1")

Outbrain.fetchRecommendations(for: request) { response in
if (response?.error != nil) {
//Handle error
}
else {
//Handle success
}
}
info

Although the fetchRecommendationsForRequest requests are asynchronous, they are all stored in the same queue, so they are handled in the order in which they were called.

info

Since SDK version 5.3.1 it is possible to request the recommendations in the async/await manner.

Task {
let request = OBRequest(url: url, widgetID: "SDK_1")
do {
let recommendations = try await Outbrain.fetchRecommendations(for: request)
} catch {
// handle error
}
}

Creating a Recommendation Request

OBRequest instance is a mandatory argument for fetchRecommendationsForRequest method. Important – the creation of an OBRequest instance should be done via one of the following two “Factory Methods”:

let request = OBRequest(url: url, widgetID: "SDK_1")
let request = OBRequest(url: url, widgetID: "SDK_1", widgetIndex: 0)

OBRequest Params

  • url (mandatory) – the URL of the page for which you’re requesting recommendations. (See Request URL for more details.)
  • widgetId (mandatory) – the widget ID (see Request Widget ID for more details).
  • widgetIndex (optional) – the widget index, required if there is more than one widget on the same app page (see Request Widget Index for more details).

Widget ID

There may be one or more locations in your app where you want to display content recommendations. In addition, you may need to display recommendations in several different widgets on the same page.

Widget IDs are pre-assigned by your account manager after you define your display requirements for the specific widget. The widget ID maps to settings related to the widget’s display, the number of recommendations returned, etc.

info

Before using the Outbrain SDK, make sure you have widget IDs assigned to all the widgets in which you’ll need to display recommendations.

Widget Index

The widget index is a numeric, zero-based value assigned sequentially to all widgets on the same page. If you plan to use (or already using) more than one widget on a single page on your Mobile app – you’ll have to implement the fetching of the recommendations in a specific order according to the guidelines below:

As a side note, it’s important to note that on Mobile apps there is no “real page”, so the meaning of a “page” in this context is a “screen” or a “page” in which 2 widgets or more are shown to the user.

For example, if you have 3 widgets on a page, you’ll assign the indexes 0, 1 and 2 to these widgets. The widget index is used to differentiate between widgets on the same page, so as not to duplicate recommendations sent to different widgets. Widgets on the same page may be of different types (e.g. footer and drawer), or may be multiple instances of the same type (e.g. multiple in-feed), that should display different recommendations.

External ID

It’s possible to add “external id” param to OBRequest which will be processed on Outbrain backend and displayed in the dashboard.

let request = OBRequest(url: url, widgetID: "SDK_1")
request.externalID = "123456789"

Handling the OBRecommendationResponse

After a successful call to fetchRecommendationsForRequest, Outbrain calls your callback or delegate method, providing an OBRecommendationResponse object. Using this object, you can iterate over the list of recommendations and display them in your app.

Here is an example implementation of an OBResponseDelegate - outbrainDidReceiveResponseWithSuccess method:

func outbrainDidReceiveResponse(withSuccess response: OBRecommendationResponse!) {
let numRecs = recommendations.count
print("received \(numRecs) recommendations")
for rec in recommendations {
// Do something with each rec
}
}

Display The Recommendations

Each OBRecommendation object contained within the OBRecommendationResponse has the following properties:

  • content – the recommendation’s title.
  • image – a thumbnail image (OBImage object) related to the recommendation. This property is optional and is included only if the widget is configured to display images.
  • source – the name of the recommendation’s source (publisher). For paid recommendations, this is the site name, and for organic recommendations, this is the section name.
  • paidLink – indicates whether this a paid or organic recommendation.

See example

Regular SDK single rec

Code

// Example: displaying a specific recommendation
// getting the recommendation
let rec = recommendations[0];

// getting the title
let title = rec.content;
// .... populate the relevant UI component with the title

// getting the source
let source = rec.source;
// .... populate the relevant UI component with the source

// getting image URL
if (rec.image != nil) {
let imageURL = rec.image.url;
// .... populate the relevant UI component with the image
}

// handling paid VS organic recommendation
if (rec.isPaidLink) {
//....Show disclaimer, add paid icon, etc…

SwiftUI code

HStack {
AsyncImage(url: recommendation.image?.url, content: { image in
image.resizable()
image.aspectRatio(contentMode: .fit)
}, placeholder: {
// Display image placeholder if needed
})
.frame(width: 100, height: 100)
.clipped()

VStack(alignment: .leading) {
Text(content)
Text(recommendation.source ?? "")
}
}
.onTapGesture {
// Handle tap
}
.addViewability(with: recommendation) // Add this modifier for Viewability tracking

Displaying The Thumbnail Image

The thumbnail image is defined by the OBImage object returned within OBRecommendation. It contains the following properties:

  • width – the image width in pixels
  • height – the image height in pixels
  • url – a URL pointing to the image file. Use the URL to render the thumbnail image (see examples in the Outbrain sample apps).

The image width and height values are those agreed upon and determined by the widget ID.

Audience Campaign

Each OBRecommendation object has the following property:

audienceCampaignsLabel – the audience campaigns label. Could be null if not audience campaigns

Ad Choices Compliance

info

Outbrain serves recommendations from demand partners that requires Ad Choices icon. as part of the recommendation creative, in order to maximize revenues for the publisher. In order to support the new demand – paid recommendations must be compliant with Ad Choices T&C.

In order to be compliant with Ad Choices T&C – Outbrain SDK will do most of the work for you. All you need to do is make sure to implement the following steps:

Regular SDK single rec

Step 1

Add AdChoices UIButton to “Recommendation View”

In the XIB or Storyboard file – you should add an UIButton “on top” of the UIImageView which displays the recommendation image (as seen in the screenshot).

The UIButton size should be exactly 30×30 and also make sure to set “hidden” property to “true” by default to promise you won’t display the ad choices icon by mistake.

You can also set the “image insets” on the Ad Choices UIButton to make the image smaller, just make sure the size is at least 30px otherwise the button will not be easily clickable.

adChoicesButton.imageEdgeInsets = UIEdgeInsetsMake(2.0, 12.0, 12.0, 2.0);
info

Important: Ad Choices (disclosure) UIButton should have width and height of 30px each.

Step 2

Displaying RTB Recommendation With Ad Choices (Disclosure) Icon

In code, at the same method where you will normally set the “image url” (rec.image.url) on the recommendation UIImageView – you should also check if the recommendation is of type RTB and if so, set the Ad Choices icon url.

// Handle RTB
if rec.shouldDisplayDisclosureIcon() {
cell.adChoicesButton.tag = indexPath.row
cell.adChoicesButton.isHidden = false
if let adChoicesImageURL = rec.disclosure.imageUrl {
Alamofire.request(adChoicesImageURL).responseImage { response in
if let image = response.result.value {
cell.adChoicesButton.setImage(image, for: .normal)
}
}
}
cell.adChoicesButton.addTarget(self, action: #selector(self.adChoicesClicked), for: .touchUpInside)

}
else {
cell.adChoicesButton.isHidden = true
}

Step 3

Handle Ad Choices (Disclosure) Icon Click

Please note, you should handle a click on the Ad Choices UIButton. In case of a click – you should open the url in an external browser (Safari or SFSafariViewController)..

Let’s expand the example above with the example code below:

cell.adChoicesButton.addTarget(self, action: #selector(self.adChoicesClicked), for: .touchUpInside)

@objc private func adChoicesClicked(sender: UIButton) {
// your code goes here
let rec = self.recs[sender.tag]
if let clickURL = rec.disclosure.clickUrl {
self.delegate?.userTappedOnAdChoicesIcon(clickURL)
}
}
info

Note: Make sure that adChoicesButton is set to hidden for non-RTB recommendations. See the code example above again.

Step 4

Simulate RTB Recommendations And Verify Your Implementation

In order to make sure you’ve implemented steps 1-3 correctly, run the SDK with:

Outbrain.testRTB = true;
Outbrain.setTestMode = true;

This will promise you will receive RTB recommendations in the response for fetchRecommendationsForRequest(). Please verify that you see the “ad choices” icon and that a click on the icon is opening in external browser as expected.

Outbrain Label

Any widget displaying Outbrain recommendations must be labeled with a header that is mutually agreed upon between the client and Outbrain. The “Outbrain widget labeling” should also be clickable – a click should open a URL generated by the SDK which is needed for GDPR and Ad Choices compliance.

To comply with Outbrain labeling guidelines:

  1. Choose one of the Outbrain logo images from the Outbrain-Resources folder.

  2. Important: Implement Click Handler

When the user clicks on the Outbrain labeling, you should open a URL generated by the SDK in the following way:

guard let url = Outbrain.getAboutURL() else {
return
}
let safariVC = SFSafariViewController(url: url)
viewController.present(safariVC, animated: true, completion: nil)

See an example in UI:

Regular SDK label

Handling Clicks

danger

Note: Method getUrl() should be called only after the “click” event. Calling getUrl() method before the click will cause the SDK to report a false “click” event on the recommendation.

  1. When a user clicks on a recommendation, you must call getUrl first:
let rec = self.recs[indexPath.row]
guard let url = Outbrain.getUrl(rec) else {
print("Outbrain.getUrl(rec) - url is null")
return
}
info

For paid recommendations, the returned URL is in paid.outbrain.com re-direct format. For organic recommendations the returned URL is in the standard (original) format. Developers should open the url “as is”, i.e. without any manipulation such as escaping or decoding.

  1. Check if it’s a paid rec by calling recommendation.isPaidLink
if (rec.isPaidLink) {
// Open all paid recommendation in SFSafariViewController
let safariVC = SFSafariViewController(url: url)
self.present(safariVC, animated: true, completion: nil)
}
else {
// It's a an organic recommendation, let's open it in our native Article ViewController
loadPostContentFromUrl(url)
}
  1. Navigate to the Recommendation

Organic Recommendations

Navigate to the organic content using your app’s standard navigation mechanism. You can find an example in the Journal sample app.

You should use SFSafariViewController or the external Safari browser to open all paid recommendations.

See the flow diagram below to understand the steps necessary for handling and navigating recommendation click:

ios-regular-widge-click-diagram

Open in SFSafariViewController

Following the above example, you should be able to open a paid recommendation in SFSafariViewController. Please use the code sample below if needed:

func openUrlInSafariVC(_ url:URL) {
let safariVC = SFSafariViewController(url: url)
self.present(safariVC, animated: true, completion: nil)
}

Widget Viewability

Outbrain Widget Viewability measurement allows Outbrain to optimize the recommendations served for the application audience, hence support a better user experience and app performance.

Widget Viewability measures if the app user has seen the widget on the device screen.

Important Concept – configureViewabilityPerListingFor() method

The most important step in the Widget Viewability implementation is to call for configureViewabilityPerListingFor() method.

For each recommendation you will need to call the following SDK method with the “container or parent” view which holds all the sub-views (image, title text, source text, etc)

Outbrain.configureViewabilityPerListing(for: contentView, withRec: rec)

SwiftUI

In order to implement Viewability tracking in SwiftUI please use the following view modifier on each view that displays a single recommendation:

.addViewability(with: recommendation)