Introduction Download SDK and Sample App Integrating with the SDK Setup Smartfeed UITableView Integration – Step 1: Create SmartFeedManager – Step 2: Connect Your Data Source to SmartFeedManager Smartfeed Optional Properties Smartfeed Delegate Smartfeed RTB Support (Optional) Smartfeed In Middle of UITableView (Optional) Read More Button
Introduction
Outbrain Smartfeed is a brand new way for publishers to integrate Outbrain recommendations in their native app in a way that feels natural to their users (infinite scrolling at the end of the original article) and seamless for app developers to integrate.
See example of how Smartfeed works below:
Download SDK and Sample App
Download links are available at Outbrain SDK – Documentation & Download Links
Integrating with the SDK
Smartfeed is an integral part of the SDK, therefore you must integrate and init the SDK according to the instructions in our main developers guide page.
Setup Smartfeed
Finally we get to the interesting part of this guide, here are the actual steps necessary for app developers to make use of Smartfeed in their application.
SmartFeedManager
is the Class responsible for managing the Smartfeed. You should create an instance of SmartFeedManager in the relevant UIViewController where the original article is displayed.
The SmartFeedManager
constructor can work with both: UICollectionView
and UITableView
. The integration is pretty similar, please refer to the one relevant to you.
UITableView Integration
Step 1: Create SmartFeedManager
We recommend to setup SmartFeedManager
in viewDidLoad
method, for example:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.delegate = self
tableView.dataSource = self
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
spinner.startAnimating()
spinner.frame = CGRect(x: 0, y: 0, width: self.tableView.frame.width, height: 44)
self.tableView.tableFooterView = spinner;
self.setupSmartFeed()
}
func setupSmartFeed() {
let baseURL = currentArticleDemoUrl
self.smartFeedManager = SmartFeedManager(url: baseURL, widgetID: smartFeedWidgetID, tableView: self.tableView)
self.smartFeedManager.delegate = self
// Optional
self.setupCustomUIForSmartFeed()
}
We initilize SmartFeedManager with:
1) baseURL – the current article URL
2) widgetID – an additional Outbrain widget ID – different from the primary widgetID id (has to be configured to be of type “smartfeed”, please consult with you account manager for more details).
3) tableView – the table view instance.
We will explain about setupCustomUIForSmartFeed()
later on in this guide.
(Optional) set the widget index
By default the “widget index” for the Smartfeed is 0, however in case there are additional Outbrain widgets on the screen besides the Smartfeed, it’s possible to set the “widget index” via:
self.smartFeedManager.outbrainWidgetIndex = 2
Step 2: Connect Your Data Source to SmartFeedManager
SmartFeedManager should be called from key methods in the table view data source.
The methods you should call SmartFeedManager
are:
1) func numberOfSections(in tableView: UITableView) -> Int
2) func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
3) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
4) func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
5) func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
numberOfSections
Smartfeed recommendations will be added into a separate section in the collection view to not interfere with the original data source implementation.
func numberOfSections(in tableView: UITableView) -> Int {
self.smartFeedManager.outbrainSectionIndex = 1 // update smartFeedManager with outbrain section index, must be the last one.
return self.smartFeedManager.numberOfSectionsInTableView()
}
numberOfRowsInSection
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section < self.smartFeedManager.outbrainSectionIndex {
return originalArticleItemsCount
}
else {
return self.smartFeedManager.smartFeedItemsCount()
}
}
cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == self.smartFeedManager.outbrainSectionIndex { // Outbrain
return self.smartFeedManager.tableView(tableView, cellForRowAt: indexPath)
}
// Your app original implementation
}
willDisplay
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.smartFeedManager.tableView(tableView, willDisplay: cell, forRowAt: indexPath)
// App Developer should configure the app cells here..
}
heightForRowAt
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == self.smartFeedManager.outbrainSectionIndex { // Outbrain
return self.smartFeedManager.tableView(tableView, heightForRowAt: indexPath)
}
return UITableViewAutomaticDimension;
}
(Optional): Implement Custom UI
For more information please refer to: iOS SDK – Smartfeed UITableView Custom UI
Smartfeed Optional Properties
smartFeedManager.disableCellShadows
Setting this property to “true” will disable shadows on each Smartfeed cell.
smartFeedManager.displaySourceOnOrganicRec
Setting this property to “true” will display the “source name” label on organic recs as well.
smartFeedManager.horizontalContainerMargin
Setting this property to value of 20.0 for example, will add margin on the “left” and “right” sides of the horizontal cell.
smartFeedManager.darkMode
Setting this property to “true” will change the Smartfeed colors scheme to “dark mode”
smartFeedManager.outbrainWidgetIndex
Set this value if there are more Outbrain widgets on the screen where the Smartfeed is displayed.
smartFeedManager.externalID
Setting this property will add extid
param to all ODB requests with the value of externalID param.
Smartfeed Delegate
Since SDK v3.7.0, app developers can now skip on the SmartFeedDelegate
implementation, in which case the SDK will handle all Smartfeed clicks by default implementation, i.e. open all links in SFSafariViewController
.
@protocol SmartFeedDelegate
-(void) userTappedOnRecommendation:(OBRecommendation *_Nonnull)rec;
-(void) userTappedOnAdChoicesIcon:(NSURL *_Nonnull)url;
-(void) userTappedOnVideoRec:(NSURL *_Nonnull)url;
-(void) userTappedOnOutbrainLabeling;
@end
An example for delegate implementation might be:
-(void) userTappedOnRecommendation:(OBRecommendation *_Nonnull)rec {
if (rec.appInstall) {
[Outbrain openAppInstallRec:rec inNavController:self.navigationController];
return;
}
NSURL *url = [Outbrain getUrl:rec];
[self presentSFSafariViewController:url];
}
-(void) userTappedOnAdChoicesIcon:(NSURL *_Nonnull)url {
[self presentSFSafariViewController:url];
}
-(void) userTappedOnVideoRec:(NSURL *_Nonnull)url {
[self presentSFSafariViewController:url];
}
-(void) userTappedOnOutbrainLabeling {
NSURL *url = Outbrain.getOutbrainAboutURL;
[self presentSFSafariViewController:url];
}
-(void) presentSFSafariViewController:(NSURL *_Nonnull)url {
SFSafariViewController *safariVC = [[SFSafariViewController alloc]initWithURL:url entersReaderIfAvailable:NO];
UINavigationController *navigationController = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
[navigationController presentViewController:safariVC animated:true completion:^{}];
}
Smartfeed RTB Support
SmartFeedManager
supports RTB “out of the box”, i.e. the displaying of the “Ad Choices” icon is done for you. All you, as the app developer, should do, is make sure to implement the click handling for the ad choices icon. On click you should open the provided URL in a browser. See example code below:
func userTapped(onAdChoicesIcon url: URL) {
print("You tapped onAdChoicesIcon")
let safariVC = SFSafariViewController(url: url)
self.navigationController?.present(safariVC, animated: true, completion: nil)
}
(Optional) Smartfeed In Middle of UITableView
Smartfeed can also be integrated in the middle of the screen so that additional non-Outbrain content can be placed below it. In order to achieve that, app developer should make the following changes.
App developer should make use of smartfeedIsReadyWithRecs()
method of SmartFeedDelegate
as shown below:
In Corresponding ViewController
self.smartFeedManager = SmartFeedManager(url: Const.baseURL, widgetID: Const.widgetID, tableView: self.tableView)
self.smartFeedManager.delegate = self
self.smartFeedManager.isInMiddleOfScreen = true
self.smartFeedManager.outbrainSectionIndex = 1 // update smartFeedManager with outbrain section index
self.smartFeedManager.fetchMoreRecommendations() // start fetching manually because Smartfeed is in the middle
In Corresponding SmartFeedDelegate
func smartfeedIsReadyWithRecs() {
if (!self.smartfeedIsReady) {
// only for the first time run reloadData() after that the Smartfeed will take care of updating itself
self.smartfeedIsReady = true
self.collectionView.reloadData()
}
}
In Corresponding Data Source
func numberOfSections(in tableView: UITableView) -> Int {
if self.smartfeedIsReady {
// numberOfSections including Smartfeed
return 3
}
else {
return 2
}
}
// number of rows in table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.smartfeedIsReady && section == self.smartFeedManager.outbrainSectionIndex {
return self.smartFeedManager.smartFeedItemsCount()
}
else {
return articleSectionItemsCount
}
}
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// create a new cell if needed or reuse an old one
var cell:UITableViewCell?
if self.smartfeedIsReady && indexPath.section == self.smartFeedManager.outbrainSectionIndex
{ // Outbrain
return self.smartFeedManager.tableView(tableView, cellForRowAt: indexPath)
}
// Continue with app implementation
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if self.smartfeedIsReady && indexPath.section == self.smartFeedManager.outbrainSectionIndex { // Outbrain
self.smartFeedManager.tableView(tableView, willDisplay: cell, forRowAt: indexPath)
if (self.smartFeedManager.hasMore && indexPath.row + 3 >= self.smartFeedManager.smartFeedItemsCount()) {
// manually fetch more recommendations when feed is near the end
self.smartFeedManager.fetchMoreRecommendations()
}
return
}
// App Developer should configure the app cells here..
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if self.smartfeedIsReady && indexPath.section == self.smartFeedManager.outbrainSectionIndex { // Outbrain
return self.smartFeedManager.tableView(tableView, heightForRowAt: indexPath)
}
// Continue with app implementation
}
(Optional) Read More Button
Read the instructions on this page to learn how to use the “Read More” functionality to increase RPM performance for your Smartfeed.