Content Display
This documentation explains how user-generated content (UGC), 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:
You will need your apiKeyConversations to implement and use Conversations with Mobile SDKs.
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
.
Before you start implementing this Mobile SDK module, verify your installation by checking the steps on the Installation page.
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
If you need to check the list of possible parameters for any of the below APIs, please refer the below links and select the API from section contents:
The available content types are described below in more detail.
- Product Display Page
- Reviews
- Questions & Answers
- Comments
- Bulk Ratings
- Author Profile Display
- Review Highlights
Loading a product display page
Objective-C SDK
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.
BVProductDisplayPageRequest* request = [[BVProductDisplayPageRequest alloc]
initWithProductId:@"test1"];
[request includeStatistics:BVProductIncludeTypeValueReviews];
[request includeStatistics:BVProductIncludeTypeValueQuestions];
// request product information, including statistics on reviews and questions/answers.
let request = BVProductDisplayPageRequest(productId: "test1")
.includeStatistics(.reviews)
.includeStatistics(.questions)
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 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)];
// 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)
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:^(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
}];
// 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
}
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;
@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
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
}
}
}
Swift SDK
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
Objective-C SDK
As shown previously, you should use a ProductDisplayPageRequest
to load the first page of UGC 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.
@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");
}];
// 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)
}
A BVReviewsRequest
requires three parameters:
productId
- the productId that you want reviews forlimit
- 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.
BVReviewsRequest* request = [[BVReviewsRequest alloc] initWithProductId:@"test1" limit:10 offset:20];
[request filterOnReviewFilterValue:BVReviewFilterValueHasPhotos relationalFilterOperatorValue:BVRelationalFilterOperatorValueEqualTo value:@"true"];
[request sortByReviewsSortOptionValue:BVReviewsSortOptionValueReviewSubmissionTime monotonicSortOrderValue:BVMonotonicSortOrderValueDescending];
// 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)
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 BVSDK;
@interface DemoReviewsViewController: UIViewController
@property (nonatomic, weak) IBOutlet BVReviewsTableView *tableView;
@end
// ...
@implementation DemoReviewsViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
import UIKit
import BVSDK
class DemoReviewsViewController: UIViewController {
@IBOutlet weak var tableView : BVReviewsTableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
- 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 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
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 } } }
-
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 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
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
}
}
Swift SDK
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
Objective-C SDK
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.
@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<nserror *=""> * _Nonnull errors) {
NSLog(@"Error loading questions");
}];
</nserror>
// 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)
}
A QuestionsAndAnswersRequest
requires the three parameters:
productId
- the productId that you want questions forlimit
- 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 questions 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.
BVQuestionsAndAnswersRequest* request = [[BVQuestionsAndAnswersRequest alloc] initWithProductId:@"test1" limit:10 offset:0];
[request filterOnQuestionFilterValue:BVQuestionFilterValueQuestionHasAnswers relationalFilterOperatorValue:BVRelationalFilterOperatorValueEqualTo value:@"true"];
[request sortByQuestionsSortOptionValue:BVQuestionsSortOptionValueQuestionLastModeratedTime monotonicSortOrderValue:BVMonotonicSortOrderValueDescending];
// 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)
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 BVSDK;
@interface DemoQuestionsViewController: UIViewController
@property (nonatomic, weak) IBOutlet BVQuestionsTableView *tableView;
@end
// ...
@implementation DemoQuestionsViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
import UIKit
import BVSDK
class DemoQuestionViewController: UIViewController {
@IBOutlet weak var questionsTableView : BVQuestionsTableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
- 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 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
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
}
}
}
- 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 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
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
}
}
Swift SDK
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
Objective-C SDK
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.
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);
}];
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)")
}
Swift SDK
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
Objective-C SDK
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.
NSArray* productIds = @[@"test1", @"test2", @"test3", @"test4"];
BVBulkRatingsRequest* request = [[BVBulkRatingsRequest alloc] initWithProductIds:productIds statistics: BVBulkRatingIncludeTypeValueBulkRatingReviews];
// 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)
Which can be loaded with:
[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
}];
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
}
Swift SDK
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
Objective-C SDK
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.
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);
}];
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)
}
Swift SDK
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.
Loading Review Highlights
Objective-C SDK
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.
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);
}];
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
}
- Pass the client ID to the configuration before creating the request to fetch Review Highlights, as shown in the following code block:
NSDictionary *configDict = @{@"clientId" : @"YOUR_CLIENT_ID", @"apiKeyConversations":@"YOUR_API_KEY"};
[BVSDKManager configureWithConfiguration:configDict
configType:BVConfigurationTypeStaging];
let configDict = ["clientId": "YOUR_CLIENT_ID",
"apiKeyConversations": "YOUR_API_KEY"];
BVSDKManager.configure(withConfiguration: configDict, configType: .staging)
Swift SDK
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()
Updated 9 months ago