The Bazaarvoice Mobile SDKs provide access to most of the core products Bazaarvoice offers. To learn more, go to the Mobile SDK documentation home page.

Contents

(+ show- hide)

This documentation explains how consumer-generated content (CGC) social media content can be displayed using the mobile SDK either by loading the Infinite Recycle View or by accessing the data directly via the API.

Introduction

Before you start implementing this Mobile SDK module, verify your installation by checking the steps on the Installation page.

Curations support from the Bazaarvoice Mobile SDK allows you to rapidly implement your custom social feeds with only a few lines of code. Display social media feeds on your home page or product page with social content tagged to your product catalog. Depending on your application requirements, there are two ways to fetch your Curations data for display:

  • BVCurationsUICollectionView (recommended) - Use our custom, sub-classed UICollectionView controller to handle the entire display, scrolling, and paging.
  • API Direct - If you have UI customization that don't fit a UICollectionView, you can call the API directly to fetch the Curations feed items you need for display.

The completed project for this code walk-through for Swift and Objective-C is in the SDK path /Examples/Curations. For a more comprehensive demonstration of the Conversations API, please also see the BVSDKDemo project under /Examples/BVSDKDemo.

You must have Bazaarvoice Curations enabled to use the Curations module. Contact Bazaarvoice to set up Curations and to get your Curations API Key.

BVCurationsUICollectionView

The BVSDK comes with a ready-to-roll display in BVCurationsUICollectionView class. This subclass of a UICollectionView handles all the flow layout, scrolling, API fetch requests, infinite scroll and adds proper badges for the social channel of each cell. If you are familiar with the fundamentals of a UICollectionView, this integration will be a snap! Once you have the basic display set-up, you will be required to:

  • Implement the BVCurationsUICollectionViewDelegate required methods.
    • Provide your own image loading and caching (e.g. SDWebImage).
  • Handle any redrawing or layout adjustments for screen rotations

You may optionally, but are encouraged to, handle the following:

  • Handle user interaction events for when a user taps a BVCurationFeedItem.
  • Handle errors that may occur while loading Curations content

Rather than provide a full tutorial of how to use the widget, we have a small code snipped below of the minimal requirements. Please also see a completed example in the GitHub repository for Swift and Objective-C.

Code example: using the BVCurationsUICollectionView

The code demo shows a minimal implementation to display a BVCurationsUICollectionView in a View Controller. The demo uses SDWebImage to perform asynchronous loading and caching of the images displayed in the Collection View Cells.

import UIKit
import BVSDK
import SDWebImage

class ViewController: UIViewController, BVCurationsUICollectionViewDelegate {

    @IBOutlet weak var curationsCollectionView: BVCurationsUICollectionView!

    let sdMngr = SDWebImageManager.shared()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set up the Curations UI display properties
        curationsCollectionView?.curationsDelegate = self
        curationsCollectionView?.groups = ["__all__"]
        // Other optional properties
        curationsCollectionView?.fetchSize = 40
        curationsCollectionView?.infiniteScrollEnabled = true
        curationsCollectionView?.itemsPerRow = 2
        curationsCollectionView?.bvCurationsUILayout = .grid
        // Makes the asynchronous API call to load the Curations feed
        curationsCollectionView?.loadFeed()
    }

    private func loadImage(imageUrl: String, completion:@escaping ((UIImage, String) -> Void)) {

        _ = self.sdMngr.loadImage(with: NSURL(string: imageUrl)! as URL,
                                         options: [],
                                         progress: { (_, _, _) in

            }, completed: { (image, _, _, _, _, url) in
                if let img = image {
                    completion(img, imageUrl)
                }
        })

    }

    // MARK: BVCurationsUICollectionViewDelegate

    func curationsLoadImage(_ imageUrl: String, completion: @escaping BVSDK.BVCurationsLoadImageCompletion) {
        self.loadImage(imageUrl: imageUrl, completion: completion)
    }

    func curationsImageIsCached(_ imageUrl: String, completion: @escaping BVCurationsIsImageCachedCompletion) {

        self.sdMngr.cachedImageExists(for: NSURL(string: imageUrl) as URL?) { (cached) in
            completion(cached, imageUrl)
        }
    }

    func curationsDidSelect(_ feedItem: BVCurationsFeedItem) {
        print("Tapped: " + feedItem.debugDescription)
    }

    func curationsFailed(toLoadFeed error: Error) {
        //Unable to get next batch of content. Handle error.
        print("An error occurred: " + error.debugDescription)
    }

}
#import "ViewController.h"
#import "ViewController.h"
#import <SDWebImage/SDWebImageManager.h>

@import BVSDK;

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Set up the Curations UI display properties
    self.curationsCollectionView.curationsDelegate = self;
    self.curationsCollectionView.groups = @[@"__all__"];
    // Other optional properties
    self.curationsCollectionView.fetchSize = 40;
    self.curationsCollectionView.infiniteScrollEnabled = YES;
    self.curationsCollectionView.itemsPerRow = 1;
    self.curationsCollectionView.backgroundColor = [UIColor lightGrayColor];
    self.curationsCollectionView.bvCurationsUILayout = BVCurationsUILayoutGrid;
    // Makes the asynchronous API call to load the Curations feed
    [self.curationsCollectionView loadFeed];

}

// MARK: BVCurationsUICollectionViewDelegate

- (void)curationsLoadImage:(NSString *)imageUrl completion:(BVCurationsLoadImageCompletion)completion {

    [[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:imageUrl] options:kNilOptions progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
        // progress
    } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
        completion(image, imageUrl);
    }];

}

- (void)curationsImageIsCached:(NSString *)imageUrl completion:(BVCurationsIsImageCachedCompletion)completion {

    [[SDWebImageManager sharedManager] cachedImageExistsForURL:[NSURL URLWithString:imageUrl] completion:^(BOOL isInCache) {
        completion(isInCache, imageUrl);
    }];

}

- (void)curationsDidSelectFeedItem:(BVCurationsFeedItem *)feedItem {
    // Handle your click logic here...
    NSLog(@"Selected item: %@", feedItem.description);
}

-(void)curationsFailedToLoadFeed:(NSError *)error {
    // Unable to get next batch of content. Handle error
    NSLog(@"An error occurred: %@", error);
}

@end

Curations API direct

Calling the Curations API with the BVSDK requires the use of two class instances and one response object:

  • BVCurationsFeedRequest - Set the required parameters in the default initializer, and optional parameters in the class properties.
  • BVCurationsFeedLoader - Makes the asynchronous request with success and failure blocks. If there are any network or API failures, they will be in an NSError object.
  • BVCurationsFeedItem - On a successful result, you will have an array of social feed items you can display in your UI.
Code Example: Using the Curations Display API

You can copy/paste the code below for a starter.

let feedRequest = BVCurationsFeedRequest(groups: ["__all__"])
// Set any other optional parameter, like geo-coordinates. See the BVCurationsFeedRequest header for fields.
feedRequest?.externalId = "productId"
feedRequest?.withProductData = true

let loader = BVCurationsFeedLoader()
loader.loadFeed(with: feedRequest, completionHandler: { (feedItems) in
    // success
    for item : BVCurationsFeedItem in feedItems! {
        print(item)
    }
    }) { (error) in
    // error
    print(error)
}
BVCurationsFeedRequest *feedRequest = [[BVCurationsFeedRequest alloc] initWithGroups:@[ @"__all__" ]];

// Set any other optional parameter, like geo-coordinates. See the BVCurationsFeedRequest header for fields.
[feedRequest setLatitude:30.2 longitude:-97.7];
[feedRequest setExternalId:@"productId"];
[feedRequest setWithProductData:YES];

BVCurationsFeedLoader *urlRequest = [[BVCurationsFeedLoader alloc] init];

[urlRequest loadFeedWithRequest:feedRequest completionHandler:^(NSArray *feedItems) {
    // success!
    for (BVCurationsFeedItem *item in feedItems){
        NSLog(@"%@", item.debugDescription);
    }
} withFailure:^(NSError *error) {
    // failure : (
    NSLog(@"Error loading feed: %@", error.localizedDescription);
}];
let feedItemQuery = BVCurationsFeedItemQuery()
feedItemQuery
    .configure(configuration)
    .field(.productId(BVIdentifier.string("productId")))
    .field(.includeProductData(true))
    .handler {
        response in
            if
        case let.failure(errors) = response {
            // error 
            return
        }
        guard
        case let.success(meta, results) = response
        else {
            return
        }
        // success 
    }
guard
let request = feedItemQuery.request
else {
    return
}
feedItemQuery.async()