This guideline is relevant for our developers who use more than one widget for a single page on their Mobile app. It’s important to note that on Mobile apps there is no “real page”, so the meaning in this context is a “screen” or a “page” in which 2 widgets or more are shown to the user.


  1. Please make sure that you set the “index” variable on each request, i.e. the first request should be sent with idx=0, the second with idx=1 and so on.

  2. The second call for “fetchRecommandations” should be executed from the callback (success or failure) of the first request. The reason we ask our developers to do this is as follows: the response of the first request contains a token from the server that should be sent together with the second request. This is all done “behind the scene” by the SDK, however in order for this to work the SDK has to wait for the response of the first call. Meaning, you, the developer, have to make sure this logic works well within your app.

Android Example

The code is from Journal sample app:

    public void fragmentBecameVisible() {
        if (! didGetRecommendations) {

    private void fetchRecommendations(String widgetId) {
        OBRequest request = new OBRequest();
        if (widgetId.equals(OBDemoWidgetID3)) {
        // Default index is 0 so the first request will be according to guidelines.

        Outbrain.fetchRecommendations(request, this);

    public void onOutbrainRecommendationsSuccess(final OBRecommendationsResponse recommendations) {
        String requestWidgetId = recommendations.getRequest().getWidgetJsId();
        didGetRecommendations = true;

        // Response from the first "fetch" call
        if (requestWidgetId.equals(OBDemoWidgetID2)) {
            // First set the result of the first call on the screen, 
            // we can't be sure the second response will be "success".

        // Response from the second "fetch" call    
        if (requestWidgetId.equals(OBDemoWidgetID3)) {


    public void onOutbrainRecommendationsFailure(Exception ex) {
        Log.e("OB", "failure = " + ex.getMessage());

Please note the following:

  1. The flow starts at fragmentBecameVisible() – there we fetch recommendations for OBDemoWidgetID2.

  2. On the “success” callback we call the second widget OBDemoWidgetID3

  3. In fetchRecommendations() for the second widget (OBDemoWidgetID3) we set idx=1

iOS Example

The code is from Journal sample app:

- (void)delayedContentLoad
    self.textView.scrollsToTop = YES;
    // If we've loaded outbrain data already, or we're currently loading 
    // then there's nothing else to do.
    if(_outbrainLoaded || _loadingOutbrain) return;

    self.textView.delegate = nil;
    OBRequest * request = [OBRequest widgetID:OBDemoWidgetID2];
    [Outbrain fetchRecommendationsForRequest:request withDelegate:self];

#pragma mark - OBResponseDelegate methods
- (void)outbrainDidReceiveResponseWithSuccess:(OBRecommendationResponse *)response
    _outbrainLoaded = YES;
    _loadingOutbrain = NO;
    _adhesionDisabled = NO;
    _adhesionLocked = NO;
    // If there are no recommendations (shouldn't happen often).  Then we
    // just don't show anything
    if(response.recommendations.count == 0)
        // .... code for handling this situation

    // Adjust the webView contentInset so we can insert our view at the bottom
    UIScrollView * sv = self.textView; // self.webView.scrollView; <!-- Maybe use this later
    sv.delegate = self;

    UIEdgeInsets insets = sv.contentInset;
    insets.bottom = self.outbrainViewHeight;
    sv.contentInset = insets;

    // If "true" we received the response of the first "fetch" request
    if (response.request.widgetIndex == 0) {
        self.outbrainClassicView.recommendationResponse = response;
        self.outbrainClassicView.frame = CGRectOffset(_outbrainClassicView.bounds, 0, sv.contentSize.height);
        [sv addSubview:self.outbrainClassicView];
        if(sv.contentOffset.y >= CGRectGetMinY(_outbrainClassicView.frame))
            _adhesionDisabled = YES;

        self.outbrainClassicView.alpha = 0.f;
        [UIView animateWithDuration:.3f
                             self.outbrainClassicView.alpha = 1.f;

        OBRequest * secondRequest = [OBRequest
        [Outbrain fetchRecommendationsForRequest:secondRequest withDelegate:self];

    else { // This is the response of the second "fetch" request
        self.outbrainHoverView.recommendationResponse = response;
        self.outbrainHoverView.frame = CGRectOffset(_outbrainHoverView.bounds, 0, CGRectGetMaxY(sv.bounds));
        [sv addSubview:self.outbrainHoverView];

        self.outbrainHoverView.alpha = 0.f;

- (void)outbrainResponseDidFail:(NSError *)response
    UIAlertView * alert = [[UIAlertView alloc] initWithTitle:response.domain message:response.userInfo[NSLocalizedDescriptionKey] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
    [alert show];

Please note the following:

  1. The flow starts at delayedContentLoad() – there we fetch recommendations for OBDemoWidgetID2.

  2. On the “success” callback we call the second widget OBDemoWidgetID3 (OBDemoWidgetID3) and we set idx=1