Mobile SDKs: Integrate Bazaarvoice into your native Android and iOS apps.
Content Display
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
This documentation explains how consumer-generated content (CGC), including reviews and statistics, as well as product information can be displayed using the mobile SDK.
Introduction
Use the Bazaarvoice Mobile SDKs to enable Conversations functionality, such as Ratings and Reviews. The Conversations module provides an easy-to-use wrapper around the Conversations API. The mobile SDK support the following Conversations display features:
The completed project for this code walkthrough for Swift and Objective-C is in the SDK path /Examples/Conversations
. For a more comprehensive demonstration of the Conversations SDK, please also see the BVSDKDemo project under /Examples/BVSDKDemo
.
Displaying content
Displaying content is centered around the idea of a Product Display Page. For example, the following example page is populated using a single ProductDisplayPageRequest
, and shown inside of a BVProductDisplayPageViewController
.
We're showing very common pieces of content here: average rating, number of reviews, and number of questions/answers. After showing the Product Display Page, you can paginate through more Reviews and Question/Answers (discussed below). Lastly, you can load Bulk Ratings for multiple products at a time, which is useful when showing stars and number of reviews on a category page.
Content types
The tabs below describe the available content types in more detail.
Loading a product display page
When showing a product display page, use a BVProductDisplayPageRequest
to fetch useful data like reviewStatistics
or to include the first 10 BVReview
reviews. Then, display this data inside a designated BVProductDisplayPageViewController
, discussed below.
First, let's look at a simple BVProductDisplayPageRequest
// request product information, including statistics on reviews and questions/answers. let request = BVProductDisplayPageRequest(productId: "test1") .includeStatistics(.reviews) .includeStatistics(.questions)
// request product information, including statistics on reviews and questions/answers. BVProductDisplayPageRequest* request = [[BVProductDisplayPageRequest alloc] initWithProductId:@"test1"]; [request includeStatistics:BVProductIncludeTypeValueReviews]; [request includeStatistics:BVProductIncludeTypeValueQuestions];
In the code above, a ProductDisplayPageRequest
is created for productId test1. We also include statistics for reviews and questions/answers. You may want to include some actual content with it, as shown below. We also sort the included reviews by their submissionTime.
// request product information, including the first 5 questions and 10 reviews, sorted by their submissionTime. let request = BVProductDisplayPageRequest(productId: "test1") .include(.reviews, limit: 10) .include(.questions, limit: 5) .sort(by: .reviewSubmissionTime, monotonicSortOrderValue: .descending)
// request product information, including statistics on reviews and questions/answers. BVProductDisplayPageRequest* request1 = [[BVProductDisplayPageRequest alloc] initWithProductId:@"test1"]; [request includeProductIncludeTypeValue:BVProductIncludeTypeValueReviews limit:10]; [request includeProductIncludeTypeValue:BVProductIncludeTypeValueQuestions limit:5]; [request sortByReviewsSortOptionValue:(BVReviewsSortOptionValueReviewSubmissionTime) monotonicSortOrderValue:(BVMonotonicSortOrderValueDescending)];
Let's load this request!
To do so, simply call the load
function on the request object, and use the success and failure blocks appropriately.
// load the data request.load({ (response: BVProductsResponse) in if let product = response.result { product.reviewStatistics?.averageOverallRating // number of stars: 4.1 product.reviewStatistics?.totalReviewCount // number of reviews: 8 product.qaStatistics?.totalQuestionCount // number of questions: 2 product.qaStatistics?.totalAnswerCount // number of answers: 4 } }) { (errors:[Error]) in // handle failure appropriately }
// load the data [request load:^(BVProductsResponse * _Nonnull response) { BVProduct* product = response.result; if (product) { product.reviewStatistics.averageOverallRating; // number of stars: 4.1 product.reviewStatistics.totalReviewCount; // number of stars: 4.1 product.qaStatistics.totalQuestionCount; // number of questions: 2 product.qaStatistics.totalAnswerCount; // number of answers: 4 } } failure:^(NSArray * _Nonnull errors) { // handle failure appropriately }];
Displaying a product display page
Use a BVProductDisplayPageViewController
, BVProductDisplayPageTableViewController
, or BVProductDisplayPageCollectionViewController
to display this content.
-
Create a new Cocoa Touch Class called ProductDisplayViewController and make it subclass
BVProductDisplayPageViewController
:And import
BVSDK
from ProductDisplayViewController. -
Now, modify
viewDidLoad
to load a ProductDisplayPageRequest and setself.product
when loaded:import BVSDK class ProductPageViewController: BVProductDisplayPageViewController { override func viewDidLoad() { super.viewDidLoad() // load product display information for product "test1" let request = BVProductDisplayPageRequest(productId: "test1") request.load({ (response: BVProductsResponse) in // tell 'BVProductDisplayPageViewController' which product is being shown in this view controller self.product = response.result }) { (errors: [Error]) in // handle error appropriately } } }
@import BVSDK; @interface ProductPageViewController : BVProductDisplayPageViewController @end @implementation ProductPageViewController - (void)viewDidLoad { [super viewDidLoad]; // load product display information for product "test1" BVProductDisplayPageRequest* request = [[BVProductDisplayPageRequest alloc] initWithProductId:@"test1"]; [request load:^(BVProductsResponse * _Nonnull response) { // tell 'BVProductDisplayPageViewController' which product is being shown in this view controller self.product = response.result; } failure:^(NSArray<NSError *> * _Nonnull errors) { // handle error appropriately }]; } @end
When showing a product display page, use a BVProductQuery
to fetch useful data like reviewStatistics
or to include the first 10 BVReview
reviews, discussed below.
First, let's look at a simple BVProductQuery
let productQuery = BVProductQuery(productId: "test1") .include(.reviews) .include(.questions)
In the code above, a ProductQuery
is created for productId test1. We also include statistics for reviews and questions/answers. You may want to include some actual content with it, as shown below. We also sort the included reviews by their submissionTime.
let productQuery = BVProductQuery(productId: "test1") .include(.reviews, limit: 10) .include(.questions, limit: 5) .sort(.reviews(.submissionTime), order: .descending)
Let's load this request!
To do so, add a handler and use the success and failure cases and call the async method on the productQuery
object.
productQuery.handler { (response: BVConversationsQueryResponse < BVProduct > ) in if case .failure(let error) = response { // handle failure appropriately return } guard case let.success(_, products) = response else { return } if let product = products.first { product.reviewStatistics?.averageOverallRating // number of stars: 4.1 product.reviewStatistics?.totalReviewCount // number of reviews: 8 product.qaStatistics?.totalQuestionCount // number of questions: 2 product.qaStatistics?.totalAnswerCount // number of answers: 4 } } .configure(config) productQuery.async()
Product Search Query
let productSearchQuery = BVProductSearchQuery(searchQuery: "Large dryer") productSearchQuery.configure(config) .handler { (response: BVConversationsQueryResponse<BVProduct>) in if case .failure(let error) = response { // handle failure appropriately return } guard case let .success(_, products) = response else { return } //success } productSearchQuery.async()
The result returns products that have both large and dryer in the external ID, product name, product brand, product description, category name or category hierarchy names.
Loading more reviews
As shown previously, you should use a ProductDisplayPageRequest
to load the first page of CGC that your users will see (up 20 reviews). When loading reviews, you should request and display reviews in a BVReviewsCollectionView
or BVReviewsTableView
container. Reviews can also include Products and Comments.
// Add a BVReviewsTableView to your UIViewController and connect the outlet. @IBOutlet weak var reviewsTableView : BVReviewsTableView! var reviews : [BVReview] = [] ... // Now load the reviews from the BVReviewsTableView. // request 10 reviews, starting at index 20 let reviewsRequest = BVReviewsRequest(productId: "test1", limit: 10, offset: 20) // Add in other options for includes, filters, and sorts on the reviewsRequest object reviewsTableView.load(reviewsRequest, success: { (response) in self.reviews = response.results self.reviewsTableView.reloadData() }) { (error) in print(error) }
// Add a BVReviewsTableView to your UIViewController and connect the outlet. @property (weak, nonatomic) IBOutlet BVReviewsTableView *reviewsTableView; @property NSArray *reviews; ... // Now load the reviews from the BVReviewsTableView. // request 10 reviews, starting at index 20 BVReviewsRequest* request = [[BVReviewsRequest alloc] initWithProductId:@"test1" limit:10 offset:20]; // Add in other options for includes, filters, and sorts on the reviewsRequest object [self.reviewsTableView load:request success:^(BVReviewsResponse * _Nonnull response) { self.reviews = response.results; [self.reviewsTableView reloadData]; } failure:^(NSArray * _Nonnull errors) { NSLog(@"Error loading reviews"); }];
A BVReviewsRequest
requires three parameters:
-
productId
- the productId that you want reviews for -
limit
- max number of reviews to fetch (maximum of 20) -
offset
- the index to start on
A combination of limit and offset should be used to load more pages of reviews upon the user's request.
You can add filters and sorts to the request, as shown below:
// request 10 reviews that have photos, starting at index 0, sorted by overall rating. let request = BVReviewsRequest(productId: "test1", limit: 10, offset: 0) .filter(on: .hasPhotos, relationalFilterOperatorValue: .equalTo, value: "true") .sort(by: .reviewRating, monotonicSortOrderValue: .ascending)
// request 10 reviews that have photos, starting at index 0, sorted by overall rating. BVReviewsRequest* request = [[BVReviewsRequest alloc] initWithProductId:@"test1" limit:10 offset:20]; [request filterOnReviewFilterValue:BVReviewFilterValueHasPhotos relationalFilterOperatorValue:BVRelationalFilterOperatorValueEqualTo value:@"true"]; [request sortByReviewsSortOptionValue:BVReviewsSortOptionValueReviewSubmissionTime monotonicSortOrderValue:BVMonotonicSortOrderValueDescending];
Similarly to the ProductDisplayPageRequest
, loading reviews is simply done by calling the load()
method on the BVReviewsCollectionView
or BVReviewsTableView
container as shown above.
Displaying reviews
Multiple reviews should be shown in one of the following container view:
-
BVReviewView
-
BVReviewsTableView
-
BVReviewsCollectionView
Each review should be shown using one of the following views:
-
BVReviewView
-
BVReviewTableViewCell
-
BVReviewCollectionViewCell
Let's create a UIViewController that holds a BVReviewsTableView
and display 10 reviews in it using BVReviewTableViewCell
.
-
Create a new Cocoa Touch Class called DemoReviewViewController and make it subclass
UIViewController
: -
Import
BVSDK
from DemoReviewViewController, and add an instance ofBVReviewsTableView
.import UIKit import BVSDK class DemoReviewsViewController: UIViewController { @IBOutlet weak var tableView : BVReviewsTableView! override func viewDidLoad() { super.viewDidLoad() } }
@import BVSDK; @interface DemoReviewsViewController: UIViewController @property (nonatomic, weak) IBOutlet BVReviewsTableView *tableView; @end // ... @implementation DemoReviewsViewController - (void)viewDidLoad { [super viewDidLoad]; } @end
-
In
DemoReviewViewController.xib
, add aUITableView
to your view and add appropriate constraints. Change its class toBVReviewsTableView
, and hook it up to yourIBOutlet
: -
Create a subclass of
UITableViewCell
named DemoReviewTableViewCell: -
Change the type of DemoReviewTableViewCell to
BVReviewTableViewCell
and add appropriate UI elements. In the code below you can override thereview
property to update the UI elements:import UIKit import BVSDK class DemoReviewTableViewCell: BVReviewTableViewCell { @IBOutlet weak var reviewTitle : UILabel! @IBOutlet weak var reviewText : UILabel! override var review: BVReview! { didSet { reviewTitle.text = review.title reviewText.text = review.reviewText } } }
@import BVSDK; @interface DemoReviewTableViewCell : BVReviewTableViewCell @property (nonatomic, weak) IBOutlet UILabel *reviewTitle; @property (nonatomic, weak) IBOutlet UILabel *reviewText; @end // ... @implementation DemoReviewTableViewCell -(void)setReview:(BVReview *)review { [super setReview:review]; self.reviewTitle.text = review.title; self.reviewText.text = review.reviewText; } @end
-
Add your reviewText and reviewTitle
UILabel
s to DemoReviewTableViewCell.xib, and hook up your outlets: -
Finally, inside DemoReviewViewController, use a
BVReviewsRequest
object to load 10 reviews. Use instances of DemoReviewTableViewCell to display:import UIKit import BVSDK class DemoReviewsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView : BVReviewsTableView! var reviews : [BVReview] = [] override func viewDidLoad() { super.viewDidLoad() self.tableView.delegate = self self.tableView.dataSource = self self.tableView.register(UINib(nibName: "DemoReviewTableViewCell", bundle: nil), forCellReuseIdentifier: "DemoReviewTableViewCell") let request = BVReviewsRequest(productId: "test1", limit: 10, offset: 20) self.tableView.load(request, success: { (response: BVReviewsResponse) in self.reviews = response.results self.tableView.reloadData() }) { (errors: [Error]) in // handle failure appropriately } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.reviews.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "DemoReviewTableViewCell") as! DemoReviewTableViewCell cell.review = self.reviews[indexPath.row] return cell } }
@import BVSDK; @interface DemoReviewsViewController : UIViewController @property (nonatomic, weak) IBOutlet BVReviewsTableView *tableView; @property (nonatomic, strong) NSArray* reviews; @end // ... @implementation DemoReviewsViewController -(void)viewDidLoad { [super viewDidLoad]; self.tableView.delegate = self; self.tableView.dataSource = self; [self.tableView registerNib:[UINib nibWithNibName:@"DemoReviewTableViewCell" bundle:nil] forCellReuseIdentifier:@"DemoReviewTableViewCell"]; BVReviewsRequest* request = [[BVReviewsRequest alloc] initWithProductId:@"test1" limit:10 offset:20]; [self.tableView load:^(BVReviewsResponse * _Nonnull response) { self.reviews = response.results; [self.tableView reloadData]; } failure:^(NSArray * _Nonnull errors) { // handle failure appropriately }]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.reviews count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { DemoReviewTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"DemoReviewTableViewCell"]; cell.review = [self.reviews objectAtIndex:indexPath.row]; return cell; } @end
let reviewQuery = BVReviewQuery(productId: "test1", limit: 10, offset: 0) .configure(config) .handler { (response: BVConversationsQueryResponse < BVReview > ) in if case .failure(let error) = response { // error return } guard case let.success(_, reviews) = response else { return } // success } reviewQuery.async()
Filter Reviews
let reviewQuery = BVReviewQuery(productId: "test1", limit: 10, offset: 4) .filter((.hasPhotos(true), .equalTo)) .filter((.hasComments(false), .equalTo)) .configure(config) .handler {}
You can also use exhaustive set of filter options whilst constructing BVReviewQuery
mentioned on this link.
Sort Reviews
let reviewQuery = BVReviewQuery(productId: "test1", limit: 10, offset: 4) .sort(.rating, order: .ascending) .configure(config) .handler {}
You can also use exhaustive set of sort options whilst constructing BVReviewQuery
mentioned on this link.
Loading Questions & Answers
Similarly to reviews, you should use a ProductDisplayPageRequest
to load the first page of Questions/Answers (up the first 20 questions). When loading questions, you should request and display questions in a BVQuestionsCollectionView
or BVQuestionsTableView
container::
// Add a BVQuestionsTableView to your UIViewController and connect the outlet. @IBOutlet weak var questionsTableView : BVQuestionsTableView! var questions : [BVQuestion] = [] ... // Now load the questions from the BVQuestionsTableView. // request 10 questions, starting at index 20 let questionsRequest = BVQuestionsAndAnswersRequest(productId: "test1", limit: 10, offset: 20) questionsTableView.load(questionsRequest, success: { (response) in self.questions = response.results self.questionsTableView.reloadData() }) { (error) in print(error) }
// Add a BVQuestionsTableView to your UIViewController and connect the outlet. @property (weak, nonatomic) IBOutlet BVQuestionsTableView *questionsTableView; @property NSArray *questions; // Now load the questions from the BVQuestionsTableView. // request 10 questions, starting at index 20 BVQuestionsAndAnswersRequest* request = [[BVQuestionsAndAnswersRequest alloc] initWithProductId:@"test1" limit:10 offset:20]; [self.questionsTableView load:request success:^(BVQuestionsAndAnswersResponse * _Nonnull response) { self.questions = response.results; [self.questionsTableView reloadData]; } failure:^(NSArray* _Nonnull errors) { NSLog(@"Error loading questions"); }];
A QuestionsAndAnswersRequest
requires the three parameters:
-
productId
- the productId that you want questions for -
limit
- max number of questions to fetch (maximum of 20) -
offset
- the index to start on
A combination of limit and offset should be used to load more pages of quesitons upon the user's request.
You can add filters and sorts to the request, as shown below:
// request 10 questions that have answers, starting at index 0, sorted by the number of answers each question has. let request = BVQuestionsAndAnswersRequest(productId: "test1", limit: 10, offset: 20) .filter(on: .questionHasAnswers, relationalFilterOperatorValue: .equalTo, value: "true") .sort(by: .questionSubmissionTime, monotonicSortOrderValue: .ascending)
// request 10 questions that have answers, starting at index 0, sorted by the number of answers each question has. BVQuestionsAndAnswersRequest* request = [[BVQuestionsAndAnswersRequest alloc] initWithProductId:@"test1" limit:10 offset:0]; [request filterOnQuestionFilterValue:BVQuestionFilterValueQuestionHasAnswers relationalFilterOperatorValue:BVRelationalFilterOperatorValueEqualTo value:@"true"]; [request sortByQuestionsSortOptionValue:BVQuestionsSortOptionValueQuestionLastModeratedTime monotonicSortOrderValue:BVMonotonicSortOrderValueDescending];
Displaying Questions & Answers
Questions & Answers should be shown in one of the following container view:
-
BVQuestionsView
-
BVQuestionsTableView
-
BVQuestionsCollectionView
-
BVAnswersView
-
BVAnswersTableView
-
BVAnswersCollectionView
Each question/answer should be shown using one of the following views:
-
BVQuestionView
-
BVQuestionTableViewCell
-
BVQuestionCollectionViewCell
-
BVAnswerView
-
BVAnswerTableViewCell
-
BVAnswerCollectionViewCell
Let's create a UIViewController that holds a BVQuestionTableView
and display 10 questions in it using BVQuestionTableViewCell
s.
-
Create a new Cocoa Touch Class called DemoQuestionViewController and make it subclass
UIViewController
: -
Import
BVSDK
from DemoQuestionViewController, and add an instance ofBVQuestionsTableView
.import UIKit import BVSDK class DemoQuestionViewController: UIViewController { @IBOutlet weak var questionsTableView : BVQuestionsTableView! override func viewDidLoad() { super.viewDidLoad() } }
@import BVSDK; @interface DemoQuestionsViewController: UIViewController @property (nonatomic, weak) IBOutlet BVQuestionsTableView *tableView; @end // ... @implementation DemoQuestionsViewController - (void)viewDidLoad { [super viewDidLoad]; } @end
-
In
DemoQuestionViewController.xib
, add aUITableView
to your view and add appropriate constraints. Change its class toBVQuestionsTableView
, and hook it up to yourIBOutlet
: -
Create a subclass of
UITableViewCell
named DemoQuestionTableViewCell: -
Change the type of DemoQuestionTableViewCell to
BVQuestionTableViewCell
and add appropriate UI elements. In the code below you can override thequestion
property to update the UI elements:import UIKit import BVSDK class DemoQuestionTableViewCell: BVQuestionTableViewCell { @IBOutlet weak var questionSummary : UILabel! @IBOutlet weak var questionDetails : UILabel! override var question: BVQuestion! { didSet { questionSummary.text = question.questionSummary questionDetails.text = question.questionDetails } } }
@import BVSDK; @interface DemoQuestionTableViewCell : BVQuestionTableViewCell @property (nonatomic, weak) IBOutlet UILabel *questionSummary; @property (nonatomic, weak) IBOutlet UILabel *questionDetails; @end // ... @implementation DemoQuestionTableViewCell -(void)setQuestion:(BVQuestion *)question { [super setQuestion:question]; self.questionSummary.text = question.questionSummary; self.questionDetails.text = question.questionDetails; } @end
-
Add your questionSummary and questionDetails
UILabel
s to DemoQuestionTableViewCell.xib, and hook up your outlets: -
Finally, inside DemoQuestionViewController, use a
BVQuestionsAndAnswersRequest
object to load 10 questions and their associated answers. Use instances of DemoQuestionTableViewCell to display:Answers are not displayed in this tutorial but should be displayed alongside questions.import UIKit import BVSDK class DemoQuestionViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView : BVQuestionsTableView! var questions : [BVQuestion] = [] override func viewDidLoad() { super.viewDidLoad() self.tableView.delegate = self self.tableView.dataSource = self self.tableView.register(UINib(nibName: "DemoQuestionTableViewCell", bundle: nil), forCellReuseIdentifier: "DemoQuestionTableViewCell") let request = BVQuestionsAndAnswersRequest(productId: "test1", limit: 10, offset: 20) self.tableView.load(request, success: { (response: BVQuestionsAndAnswersResponse) in self.questions = response.results self.tableView.reloadData() }) { (errors: [Error]) in // handle failure appropriately } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.questions.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "DemoQuestionTableViewCell") as! DemoQuestionTableViewCell cell.question = self.questions[indexPath.row] return cell } }
@import BVSDK; @interface DemoQuestionsViewController : UIViewController<UITableViewDelegate, UITableViewDataSource> @property (nonatomic, weak) IBOutlet BVQuestionsTableView *tableView; @property (nonatomic, strong) NSArray<BVQuestion*>* questions; @end // ... @implementation DemoQuestionsViewController -(void)viewDidLoad { [super viewDidLoad]; self.tableView.delegate = self; self.tableView.dataSource = self; [self.tableView registerNib:[UINib nibWithNibName:@"DemoQuestionTableViewCell" bundle:nil] forCellReuseIdentifier:@"DemoQuestionTableViewCell"]; BVQuestionsAndAnswersRequest* request = [[BVQuestionsAndAnswersRequest alloc] initWithProductId:@"test1" limit:10 offset:20]; [self.tableView load:request success:^(BVQuestionsAndAnswersResponse * _Nonnull response) { self.questions = response.results; [self.tableView reloadData]; } failure:^(NSArray<NSError *> * _Nonnull errors) { // handle failure appropriately }]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.questions count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { DemoQuestionTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"DemoQuestionTableViewCell"]; cell.question = [self.questions objectAtIndex:indexPath.row]; return cell; } @end
let questionQuery = BVQuestionQuery(productId: "test1", limit: 10, offset: 0) .configure(config) .handler { (response: BVConversationsQueryResponse < BVQuestion > ) in if case .failure(let error) = response { // error return } guard case let.success(_, questions) = response else { return } // success } questionQuery.async()
Filter Questions & Include Answers
let questionQuery = BVQuestionQuery(productId: "test1", limit: 10,offset: 0) .include(.answers) .filter((.hasAnswers(true), .equalTo)) .configure(config) .handler {}
You can also use exhaustive set of filter options whilst constructing BVQuestionQuery
mentioned on this link.
Sort Questions
let questionQuery = BVQuestionQuery(productId: "test1", limit: 10, offset: 0) .sort(.totalAnswerCount, order: .descending) .configure(config) .handler {}
You can also use exhaustive set of sort options whilst constructing BVQuestionQuery
mentioned on this link.
Loading review comments
Comments can be loaded either by a single comment ID, or you can load comments by a review ID with limit and offset parameters. Simply construct a BVCommentsRequest
object and choose one of the default initializers provided. The examples provided below demonstrate how to fetch a list of comments from a given review ID.
let limit : UInt16 = 99 let offset : UInt16 = 0 let request = BVCommentsRequest(reviewId: "myReviewId", limit: limit, offset: offset) // Optionally, comments can have includes, filters, and sorts added to the request. request.addInclude(.reviews) request.addFilter(.contentLocale, filterOperator: .equalTo, value: "en_US") request.addCommentSort(.commentsLastModeratedTime, order: .descending) request.load({ (response) in self.comments = response.results // Array of BVComment objects // display comments in your UI }) { (error) in print("ERROR fetching comments: \(error.first!.localizedDescription)") }
BVCommentsRequest *request = [[BVCommentsRequest alloc] initWithProductId:@"myProductId" andReviewId:@"myReviewId" limit:99 offset:0]; // Optionally, comments can have includes, filters, and sorts added to the request. [request includeCommentIncludeTypeValue:BVCommentIncludeTypeValueCommentReviews]; [request sortByCommentsSortOptionValue:BVCommentsSortOptionValueCommentLastModeratedTime monotonicSortOrderValue:BVMonotonicSortOrderValueDescending]; [request filterOnCommentFilterValue:BVCommentFilterValueCommentContentLocale relationalFilterOperatorValue:BVRelationalFilterOperatorValueEqualTo value:@"en_US"]; [request load:^(BVCommentsResponse * _Nonnull response) { // success self.comments = response.results; // Array of BVComment objects // display comments in your UI } failure:^(NSArray<NSError *> * _Nonnull errors) { // error NSLog(@"ERROR Loading Comments: %@", errors.firstObject.localizedDescription); }];
Comments can be loaded either by a single comment ID, or you can load comments by a review ID with limit and offset parameters. Simply construct a BVCommentsQuery
object and choose one of the default initializers provided. The examples provided below demonstrate how to fetch a list of comments from a given review ID.
let commentQuery = BVCommentsQuery(productId: "productId", reviewId: "reviewId",limit: 10) commentQuery .configure(config) .handler { (response: BVConversationsQueryResponse < BVComment > ) in if case .failure(let error) = response { // error return } guard case let.success(_, comments) = response else { return } // success } commentQuery.async()
Filter Review Comments
let commentQuery = BVCommentsQuery(productId: "productId", reviewId: "reviewId",limit: 10) commentQuery .filter((.contentLocale(Locale(identifier: "en_US")), .equalTo)) .configure(config) .handler {}
You can also use exhaustive set of filter options whilst constructing BVCommentsQuery
mentioned on this link.
Sort Review Comments
let commentQuery = BVCommentsQuery(productId: "productId", reviewId: "reviewId",limit: 10) commentQuery .sort(.submissionTime, order: .descending) .configure(config) .handler {}
You can also use exhaustive set of sort options whilst constructing BVCommentsQuery
mentioned on this link.
Showing bulk ratings
To show product rating statistics on a category page, use a BVBulkRatingsRequest
. For example, on a category page like this one:
Getting each product's rating statistics can be done with the following single request:
// Load rating statistics for four products. Can load up to 50 per request. let productIds = ["test1", "test2", "test3", "test4"] let request = BVBulkRatingsRequest(productIds: productIds, statistics: .bulkRatingAll)
// Load rating statistics for four products. Can load up to 50 per request. NSArray* productIds = @[@"test1", @"test2", @"test3", @"test4"]; BVBulkRatingsRequest* request = [[BVBulkRatingsRequest alloc] initWithProductIds:productIds statistics: BVBulkRatingIncludeTypeValueBulkRatingReviews];
Which can be loaded with:
request.load({ (response: BVBulkRatingsResponse) in let ratings = response.results for rating in ratings { let productId = rating.productId let averageOverallRating = rating.reviewStatistics?.averageOverallRating let totalReviewCount = rating.reviewStatistics?.totalReviewCount } }) { (errors: [Error]) in // handle failure appropriately }
[request load:^(BVBulkRatingsResponse * _Nonnull response) { NSArray* ratings = response.results; for (BVProductStatistics* rating in ratings) { NSString* productId = rating.productId; NSNumber* averageOverallRating = rating.reviewStatistics.averageOverallRating; NSNumber* totalReviewCount = rating.reviewStatistics.totalReviewCount; } } failure:^(NSArray * _Nonnull errors) { // handle failure appropriately }];
To show product rating statistics on a category page, use a BVProductStatisticsQuery
. For example, on a category page like this one:
Getting each product's rating statistics can be done with the following single request:
let productIds = ["test1", "test2", "test3", "test4"] let usLocale: Locale = Locale(identifier: "en_US") guard let productStatisticsQuery = BVProductStatisticsQuery(productIds: productIds) else { return } productStatisticsQuery .stats(.nativeReviews) .stats(.reviews) .filter((.contentLocale(usLocale), .equalTo)) .configure(config) .handler { (response: BVConversationsQueryResponse<BVProductStatistics>) in if case .failure(let error) = response { print(error) return } guard case let .success(_, productStatistics) = response else { return } guard let firstProductStatistic: BVProductStatistics = productStatistics.first, let reviewStatistics = firstProductStatistic.reviewStatistics, let nativeReviewStatistics = firstProductStatistic.nativeReviewStatistics else { return } print(reviewStatistics) } productStatisticsQuery.async()
You can also use exhaustive set of filter options whilst constructing BVProductStatisticsQuery
mentioned on this link.
Loading an author's profile
An author's profile for Conversations begins with a BVAuthorRequest
object. This request object is all you need to create parameters and obtain an author's profile. The response for an author is found in the response object BVAuthorResponse
. Author profile responses can include Reviews, Questions, and Answers written by the author and approved for publishing.
Badge display
Please note that image links are not returned from the Conversations API. The display for Conversation API clients is left up to the client's creative interpretation. For more information please see the Conversations Developer documentation on Badges.
let request = BVAuthorRequest(authorId: "theAuthorsId") // stats includes, optional .includeStatistics(.authorAnswers) .includeStatistics(.authorQuestions) .includeStatistics(.authorReviews) // other includes, optional .include(.authorReviews, limit: 10) .include(.authorQuestions, limit: 10) .include(.authorAnswers, limit: 10) .include(.authorReviewComments, limit: 10) // sorts, optional .sort(by: .answerSubmissionTime, monotonicSortOrderValue: .descending) .sort(by: .reviewSubmissionTime, monotonicSortOrderValue: .descending) .sort(by: .questionSubmissionTime, monotonicSortOrderValue: .descending) request.load({ (response) in // success -- load data into your UI print(response) }) { (error) in // error - handle error print(error) }
BVAuthorRequest *request = [[BVAuthorRequest alloc] initWithAuthorId: @"authorId"]; [request includeStatistics:BVAuthorIncludeTypeValueAuthorReviewComments]; [request includeStatistics:BVAuthorIncludeTypeValueAuthorQuestions]; [request includeStatistics:BVAuthorIncludeTypeValueAuthorAnswers]; [request includeAuthorIncludeTypeValue:BVAuthorIncludeTypeValueAuthorAnswers limit:5]; [request includeAuthorIncludeTypeValue:BVAuthorIncludeTypeValueAuthorQuestions limit:5]; [request includeAuthorIncludeTypeValue:BVAuthorIncludeTypeValueAuthorReviewComments limit:5]; [request includeAuthorIncludeTypeValue:BVAuthorIncludeTypeValueAuthorReviews limit:5]; [request load:^(BVAuthorResponse * _Nonnull response) { // Success! NSLog(@"Succesfully loaded profile: %@", response); } failure:^(NSArray * _Nonnull errors) { // Error : ( NSLog(@"ERROR loading author: %@", errors.description); }];
An author's profile for Conversations begins with a BVAuthorQuery
object. This request object is all you need to create parameters and obtain an author's profile. The response for an author is found in the response object BVConversationsQueryResponse<BVAuthor>
. Author profile responses can include Reviews, Questions, and Answers written by the author and approved for publishing.
Badge display
Please note that image links are not returned from the Conversations API. The display for Conversation API clients is left up to the client's creative interpretation. For more information please see the Conversations Developer documentation on Badges.
let authorQuery = BVAuthorQuery(authorId: "AuthorId") // stats includes .stats(.answers) .stats(.questions) .stats(.reviews) // other includes .include(.reviews, limit: 10) .include(.questions, limit: 10) .include(.answers, limit: 10) .include(.comments, limit: 10) // sorts .sort(.answers(.submissionTime), order: .descending) .sort(.reviews(.submissionTime), order: .descending) .sort(.questions(.submissionTime), order: .descending) .configure(config) .handler { (response: BVConversationsQueryResponse<BVAuthor>) in // success if case .failure(let error) = response { print(error) return } guard case let .success(_, authors) = response else { return } guard let author: BVAuthor = authors.first, let qaStatistics: BVQAStatistics = author.qaStatistics, let reviewStatistics: BVReviewStatistics = author.reviewStatistics, let ratingDistribution: BVRatingDistribution = reviewStatistics.ratingDistribution, let averageOverallRating: Double = reviewStatistics.averageOverallRating, let reviews: [BVReview] = author.reviews, let questions: [BVQuestion] = author.questions, let answers: [BVAnswer] = author.answers, let comments: [BVComment] = author.comments else { return } } authorQuery.async()
You can also use exhaustive set of filter options whilst constructing BVAuthorQuery
mentioned on this link.
You can also use exhaustive set of sort options whilst constructing BVAuthorQuery
mentioned on this link.
To show product rating statistics on a category page, use a BVBulkRatingsRequest
. For example, on a category page like this one:
Getting each product's rating statistics can be done with the following single request:
// Load rating statistics for four products. Can load up to 50 per request. let productIds = ["test1", "test2", "test3", "test4"] let request = BVBulkRatingsRequest(productIds: productIds, statistics: .All)
// Load rating statistics for four products. Can load up to 50 per request. NSArray* productIds = @[@"test1", @"test2", @"test3", @"test4"]; BVBulkRatingsRequest* request = [[BVBulkRatingsRequest alloc] initWithProductIds:productIds statistics:BulkRatingsStatsTypeReviews];
Which can be loaded with:
request.load({ (response: BVBulkRatingsResponse) in let ratings = response.results for rating in ratings { let productId = rating.productId let averageOverallRating = rating.reviewStatistics?.averageOverallRating let totalReviewCount = rating.reviewStatistics?.totalReviewCount } }) { (errors: [NSError]) in // handle failure appropriately }
[request load:^(BVBulkRatingsResponse * _Nonnull response) { NSArray* ratings = response.results; for (BVProductStatistics* rating in ratings) { NSString* productId = rating.productId; NSNumber* averageOverallRating = rating.reviewStatistics.averageOverallRating; NSNumber* totalReviewCount = rating.reviewStatistics.totalReviewCount; } } failure:^(NSArray * _Nonnull errors) { // handle failure appropriately }];
To show product rating statistics on a category page, use a BVProductStatisticsQuery
. For example, on a category page like this one:
Getting each product's rating statistics can be done with the following single request:
let productIds = ["test1", "test2", "test3", "test4"] let productStatisticsQuery = BVProductStatisticsQuery(productIds: productIds) .handler { (response: BVConversationsQueryResponse < BVProductStatistics > ) in if case .failure(let error) = response { // handle failure appropriately return } guard case let.success(_, productStatistics) = response else { return } let ratings = productStatistics for rating in ratings { let productId = rating.productId let averageOverallRating = rating.reviewStatistics ? .averageOverallRating let totalReviewCount = rating.reviewStatistics ? .totalReviewCount } } productStatisticsQuery.async(
Loading Review Highlights
Load Review Highlights (PROS and CONS) by specifying a product ID and client ID.
- Construct a
BVReviewHighlightsRequest
object with the initializer provided and pass the product ID. The example provided below demonstrates how to fetch Review Highlights for a given product ID.let request = BVReviewHighlightsRequest(productId: "productId") request.load({ (response) in if let positives = response.reviewHighlights.positives { // Array of BVReviewHighlight objects // display positives in your UI for positive in positives { let title = positive.title // PRO title } } if let negatives = response.reviewHighlights.negatives { // Array of BVReviewHighlight objects // display negatives in your UI for negative in negatives { let title = negative.title // CON title } } }) { (error) in // handle failure appropriately }
BVReviewHighlightsRequest *reviewHighlightsRequest = [[BVReviewHighlightsRequest alloc] initWithProductId:@"productId"]; [reviewHighlightsRequest load:^(BVReviewHighlightsResponse * _Nonnull response) { NSArray<BVReviewHighlight *> *positives = response.reviewHighlights.positives; for (BVReviewHighlight *positive in positives) { NSString *title = positive.title; // PRO title } NSArray<BVReviewHighlight *> *negatives = response.reviewHighlights.negatives; for (BVReviewHighlight *negative in negatives) { NSString *title = negative.title; // CON title } } failure:^(NSArray<NSError *> * _Nonnull errors) { // error NSLog(@"ERROR Loading Review Highlights: %@", errors.firstObject.localizedDescription); }];
- Pass the client ID to the configuration before creating the request to fetch Review Highlights, as shown in the following code block:
let configDict = ["clientId": "YOUR_CLIENT_ID", "apiKeyConversations": "YOUR_API_KEY"]; BVSDKManager.configure(withConfiguration: configDict, configType: .staging)
NSDictionary *configDict = @{@"clientId" : @"YOUR_CLIENT_ID", @"apiKeyConversations":@"YOUR_API_KEY"}; [BVSDKManager configureWithConfiguration:configDict configType:BVConfigurationTypeStaging];
Load Review Highlights (PROS and CONS) by passing a client ID and product ID. Simply construct a
BVProductReviewHighlightsQuery
object with the initializer provided and pass the client ID and product ID. The example provided below demonstrates how to fetch Review Highlights for a given client ID and product ID.
var config: BVReviewHighlightsConfiguration = { () -> BVReviewHighlightsConfiguration in let analyticsConfig: BVAnalyticsConfiguration = .configuration(locale: Locale(identifier: "en_US"), configType: .staging(clientId: "clientId")) return BVReviewHighlightsConfiguration.display(configType: .staging(clientId: "clientId"), analyticsConfig: analyticsConfig) }() let reviewHighlightsQuery = BVProductReviewHighlightsQuery(clientId: "clientId", productId: “testproductId") .configure(config) .handler { (response: BVReviewHighlightsQueryResponse<BVReviewHighlights>) in if case .failure(let error) = response { print(error) return } guard case let .success(reviewHighlights) = response else { return } if let negatives = reviewHighlights.negatives { for negative in negatives { print(negative.title) } } if let positives = reviewHighlights.positives { for positive in positives { print(positive.bestExamples?.first?.reviewTitle) } } } reviewHighlightsQuery.async()