Product Recommendations

This documentation explains how to retrieve and display Product Recommendations.

Introduction

🚧

The Product Recommendations module is currently in limited beta release. If you'd like to participate, contact us.

Use the following guide to fetch and display product recommendations in your iOS app with Bazaarvoice Mobile SDKs. The instructions include Swift and Objective-C implementation to display Product Recommendations in a UICollectonView. If you are familiar with the design pattern of implementing a UICollectionView or UITableView in iOS, implementing the Product Recommendations module should be straightforward.

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

🚧

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

Set user information

After a user is authenticated inside your user login workflow, set user information inside the BVSDKManager#sharedManager() object.

📘

You must give the userAuthString created with your existing Bazaarvoice implementation logic to the BVSDKManager object. However, the steps to encrypt your userAuthString are applicable even if you are not a Conversations client.

Example authentication string for testing

If you haven't yet set up an authorization token, use the User Authentication Token example.

Displaying product recommendations

Product recommendations are simply views presented to users. Use the classes you already use in your storyboards to display the recommendations. You can format them to match your app's visual design. When a set of product recommendations loads, your app receives an array of BVRecommendedProduct objects that contains its assets, and the app (rather than the SDK) is then responsible for displaying each BVRecommendedProduct object.

Built-in views

THe Bazaarvoice Mobile SDK provides the following view containers to show multiple product recommendations:

  • BVProductRecommendationsCollectionView
  • BVProductRecommendationsTableView
  • BVProductRecommendationsContainer

Use the above classes as the base view for the container where you show your product recommendations. The Mobile SDK also provides the following view objects to show a single product recommendation:

  • BVRecommendationCollectionViewCell
  • BVRecommendationTableViewCell
  • BVProductRecommendationView

Use the above classes as the base class of the view where you show the product recommendation.

Example usage

The following example shows an implementation of BVProductRecommendationsCollectionView. Follow this example to produce a scrollable view of product recommendations:

Create a subclass of BVRecommendationCollectionViewCell

First, complete the following steps to create a subclass of BVRecommendationCollectionViewCell called DemoCell

  1. Create a UICollectionViewCell by selecting File > New > File.

  1. Use the following code to set its superclass as BVRecommendationCollectionViewCell in the DemoCell file, and add appropriate view outlets.

📘

The starRating object in this example is done with the open-source project HCSStarRatingView.

//  DemoCell.swift
 
import BVSDK
import HCSStarRatingView
 
class DemoCell: BVRecommendationCollectionViewCell {
 
    @IBOutlet weak var productName : UILabel!
    @IBOutlet weak var price : UILabel!
    @IBOutlet weak var numReview : UILabel!
    @IBOutlet weak var rating : UILabel!
    @IBOutlet weak var productImageView : UIImageView!
    @IBOutlet weak var starRating : HCSStarRatingView!
 
    override var bvRecommendedProduct: BVRecommendedProduct! {
 
        didSet {
 
            let imageUrl = NSURL(string: bvRecommendedProduct.imageURL)
            self.productName.text = bvRecommendedProduct.productName
            self.rating.text = "\(bvRecommendedProduct.averageRating ?? 0)"
            self.numReview.text = "(\(bvRecommendedProduct.numReviews ?? 0) reviews)"
            self.starRating.value = (CGFloat)(bvRecommendedProduct.averageRating.floatValue)
            self.productImageView?.sd_setImageWithURL(imageUrl)
 
        }
 
    }
 
}
// DemoCell.m
//
#import "DemoCell.h"
#import <SDWebImage/UIImageView+WebCache.h>
 
@interface DemoCell ()
 
@property IBOutlet UILabel *productName;
@property IBOutlet UILabel *price;
@property IBOutlet UILabel *numReview;
@property IBOutlet UILabel *rating;
@property IBOutlet UIImageView *productImageView;
@property IBOutlet HCSStarRatingView *starRating;
 
@end
 
@implementation DemoCell
 
- (void)setBvRecommendedProduct:(BVRecommendedProduct *)bvRecommendedProduct {
 
    super.bvRecommendedProduct = bvRecommendedProduct;
 
    NSURL *url = [NSURL URLWithString:self.bvRecommendedProduct.imageURL];
    [self.productImageView sd_setImageWithURL:url];
    self.productName.text = bvRecommendedProduct.productName;
    self.rating.text = [NSString stringWithFormat:@"%.1f", [bvRecommendedProduct.averageRating floatValue]];
    self.starRating.value = [bvRecommendedProduct.averageRating floatValue];
    self.numReview.text = [NSString stringWithFormat:@"(%ld)", [bvRecommendedProduct.numReviews longValue]];
    self.price.text = bvRecommendedProduct.price;
 
}
 
@end

📘

The above DemoCell outlets are suggestions for building a custom cell. The outlets map efficiently to each BVRecommendedProduct data object. However, the outlets are not required and you can configure your cell any way you want.

  1. In DemoCell.xib, add and position your views and hook up your outlets, as shown in the following screenshot.

Create a BVProductRecommendationsCollectionView

Next, complete the following steps to create a BVProductRecommendationsCollectionView. In this example, you'll create a UIViewController and put a BVProductRecommendationsCollectionView inside it.

  1. Create a UIViewController by selecting File > New > File.
  1. Add an outlet for the collection view:
class DemoViewController: UIViewController {
    @IBOutlet weak var recommendationsView : BVProductRecommendationsCollectionView!
}
// DemoViewController.h
 
#import <UIKit/UIKit.h>
#import <BVSDK/BVRecommendations.h>
@interface DemoViewController : UIViewController
 
@property IBOutlet BVProductRecommendationsCollectionView *recommendationsView;
 
@end
  1. Add a UICollectionView to your nib, and set its class to BVProductRecommendationsCollectionView.
  1. Connect the BVProductRecommendationsCollectionView to its outlet, recommendationsView.

Get product recommendations

Next, complete the following steps to get product recommendations for a user.

  1. Use the following code to fetch product recommendations and store them in a variable for later use. You'll also set up your recommendationsView delegate and data source, and register the nib you created earlier.
class DemoViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
 
    @IBOutlet weak var recommendationsView : BVProductRecommendationsCollectionView!
    var recommendations : [BVRecommendedProduct] = []
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        recommendationsView.registerNib(UINib(nibName: "DemoCell", bundle: nil), forCellWithReuseIdentifier: "DemoCellIdentifier")
 
        self.recommendationsView.delegate = self
        self.recommendationsView.dataSource = self
 
        let request = BVRecommendationsRequest(limit: 20)
        self.recommendationsView.loadRequest(request, completionHandler: { (recommendations:[BVRecommendedProduct]) in
 
            self.recommendations = recommendations
            self.recommendationsView.reloadData()
 
        }) { (error:NSError) in
            // handle error case
        }
    }
}

//  DemoViewController.m
 
#import "DemoViewController.h"
#import "DemoCell.h"
 
@interface DemoViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
 
@property NSArray<BVRecommendedProduct *>* products;
 
@end
 
@implementation DemoViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    self.products = [NSArray array];
 
    UINib* nib = [UINib nibWithNibName:@"DemoCell" bundle:nil];
    [self.recommendationsView registerNib:nib forCellWithReuseIdentifier:@"DemoCellIdentifier"];
 
    self.recommendationsView.delegate = self;
    self.recommendationsView.dataSource = self;
 
    [self loadRecommendations];
 
}
 
// Fetch the product recommenations from the API method on the BVRecommendationsCollectionView container.
- (void)loadRecommendations {
 
    BVRecommendationsRequest *request = [[BVRecommendationsRequest alloc] initWithLimit:20];
 
    [self.recommendationsView loadRequest:request completionHandler:^(NSArray<BVRecommendedProduct *> * proudcts) {
        NSLog(@"Recommendations Result: %@", proudcts.description);
        self.products = proudcts;
        [self.recommendationsView reloadData];
    } errorHandler:^(NSError * error) {
        NSLog(@"ERROR: %@", error.localizedDescription);
    }];
 
}
 
// Lays out the recommendationView with horitontal scrolling
- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];
 
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.recommendationsView.collectionViewLayout;
    layout.itemSize = CGSizeMake(self.recommendationsView.bounds.size.height, self.recommendationsView.bounds.size.height);
 
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    layout.itemSize = CGSizeMake(self.recommendationsView.bounds.size.width / 2, self.recommendationsView.bounds.size.width / 2);
 
    layout.minimumInteritemSpacing = 0;
    layout.minimumLineSpacing = 0;
}
 
@end
  1. Create and complete collectionView:numberOfItemsInSection.
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.recommendations.count ?? 0
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return self.products.count;
}
  1. Create and complete collectionView:cellForItemAtIndexPath.

📘

Image loading in this demo uses SDWebImage

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
 
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("DemoCellIdentifier", forIndexPath: indexPath) as! DemoCell
 
    let product = recommendations[indexPath.row]
    cell.bvProduct = product
 
    return cell;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
 
    DemoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"DemoCellIdentifier" forIndexPath:indexPath];
 
    cell.bvRecommendedProduct = [self.products objectAtIndex:indexPath.row];
    NSURL *url = [NSURL URLWithString:cell.bvRecommendedProduct.imageURL];
    [cell.productImageView sd_setImageWithURL:url];
 
    // initialize your other outlets here...
 
    return cell;
 
}
let profileQuery = BVRecommendationsProfileQuery()
profileQuery
    .configure(configuration)
    .field(.brandId("brandId"))
    .field(.include(.interests))
    .field(.include(.categories))
    .field(.include(.brands))
    .field(.include(.recommendations))
    .handler {
        response in
            if
        case let.failure(errors) = response {
            // error
            return
        }
        guard
        case let.success(meta, result) = response
        else {
            return
        }
        // success: result is of type [BVRecommendationsProfile]
    }
profileQuery.async()

Run the app

The app should populate the collection view with product recommendations. Although the app should run correctly, it will still need styling to look professional.