---
updatedAt: 2026-03-30T09:18:15.000Z
agentTools:
  projectIndex: https://developers.bazaarvoice.com/v1.0-MobileSDK/llms.txt
---

# Content Submission

This documentation explains the mechanics of submitting user-generated content (UGC) to Bazaarvoice using the Mobile SDK.

# Introduction

The BVSDK makes it easy to upload user-generated content (Reviews, Questions, Answers) to the Bazaarvoice platform. The [full API documentation](/v1.0-ConversationsAPI/docs/home) details what each field represents which is not covered here. Contact Bazaarvoice to set up Conversations if you haven't done so already.

> 📘
>
> 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](/v1.0-MobileSDK/docs/ios-installation) page.

# Using Conversations Submission API

After you install the Mobile SDK, complete the following steps to submit user-generated content.

## Step 1: View form options

For each option available in a submission form, there is a boolean flag determining whether it is a required field or not. You can discover this by iterating through the available form fields, which can be found by making a preview submission request.

These form fields may also contain extra information, such as available submission values, and keys for fields specific to your config such as context data values, etc.

```objectivec
// The review is the object of BVReviewSubmission.
review.submit({ (reviewSubmission) in
  // formFieldIdentifier is the name of the key that must be used for submission
  // formField contains metadata
  reviewSubmission.formFields // Here you will get the formFields
  }, failure: { (errors) in
     // handle error
})
```
```swift
guard let reviewSubmission = BVReviewSubmission(productId: "test1")
else { return }
reviewSubmission
  .configure(config)
  .add(.form)
  .handler { result in
    if case let .failure(errors) = result {
      errors.forEach { print($0) }
      return
    }
    guard case let .success(meta, _) = result else {
      return
    }
    if let formFields = meta.formFields {
      for formField in formFields {
        let formFieldIdentifier = formField.identifier
        // formFieldIdentifier is the name of the key that must be used for submission
        let isRequired = formField.required
        // Whether this field is required or optional
      }
    }
  }
reviewSubmission.async()
```

## Step 2: Send submission request

* [Review Submission](/v1.0-MobileSDK/docs/ios-content-submission#review-submission)
* [Progressive Submission](/v1.0-MobileSDK/docs/ios-content-submission#progressive-submission)
* [Question Submission](/v1.0-MobileSDK/docs/ios-content-submission#question-submission)
* [Answer Submission](/v1.0-MobileSDK/docs/ios-content-submission#answer-submission)
* [Review Comment Submission](/v1.0-MobileSDK/docs/ios-content-submission#review-comment-submission)
* [Feedback Submission](/v1.0-MobileSDK/docs/ios-content-submission#feedback-submission)

### Review submission

Create a `BVReviewSubmission` object and fill out appropriate fields.

> 📘
>
> A `BVReviewSubmission` object requires a `reviewTitle`, `reviewText`, `rating`, and `productId` (for which this review corresponds to).

#### Objective-C SDK

```objectivec
BVReviewSubmission* review = [[BVReviewSubmission alloc] initWithReviewTitle:@"Review title goes here"
                                                                reviewText:@"Review text goes here"
                                                                    rating:4
                                                                 productId:@"test1"];
review.userNickname = userNickname; // "Samantha55"
review.userId = userId;             // user's external ID
review.userEmail = userEmail;       // "test@test.com"
review.sendEmailAlertWhenPublished = [NSNumber numberWithBool:YES];
review.agreedToTermsAndConditions  = [NSNumber numberWithBool:YES];
 
// user added a photo to this review
[review addPhoto: userPhoto withPhotoCaption: userPhotoCaption];
 
// add youtube video link, if your configuration supports it
[review addVideo: userYouTubeUrl withCaption: userVideoCaption uploadVideo
: NO];
 
// add video bundle url to upload, if your configuration supports it
[review addVideo: videoPath withCaption: userVideoCaption uploadVideo
: YES];
 
// Submitting this review is as easy as calling submit
[review submit:^(BVSubmissionResponse<BVSubmittedReview *> * _Nonnull) {
  // review submitted successfully!
} failure:^(NSArray<NSError *> * _Nonnull errors) {
  // handle failure appropriately
}];
```
```swift
let review = BVReviewSubmission(reviewTitle: "Review title goes here",
                               reviewText: "Review text goes here",
                                   rating: 4,
                                productId: "test1")
review.userNickname = userNickname // "Samantha55"
review.userId = userId             // user's external ID
review.userEmail = userEmail       // "test@test.com"
review.sendEmailAlertWhenPublished = true
review.agreedToTermsAndConditions  = true
 
// user added a photo to this review
review.addPhoto(userPhoto, withPhotoCaption: userPhotoCaption)
 
// add youtube video link, if your configuration supports it
review.addVideo(userYouTubeUrl, withCaption: userVideoCaption, uploadVideo: false)

// add video bundle url to upload, if your configuration supports it
review.addVideo(videoPath, withCaption: userVideoCaption, uploadVideo: true)
 
// Submitting this review is as easy as calling submit
review.submit({ (reviewSubmission: BVSubmissionResponse<BVSubmittedReview>) in
  // review submitted successfully!
}, failure: { (errors: [Error]) in
  // handle failure appropriately
})
```

#### Swift SDK

```swift
let review: BVReview = BVReview(
  productId: "test1",
  reviewText: "Review text goes here. Review body. Review Body. !!!",
  reviewTitle: "Review title goes here",
  reviewRating: 4)
 
guard let reviewSubmission = BVReviewSubmission(review) else {
  return
}
 
reviewSubmission
  .add(.nickname("Nick"))
  .add(.additional(name: "DateOfUserExperience", value: "2021-04-03"))
  .add(.agree(true))
  .add(.photos([BVPhoto()])) //api can handle multiple BVPhoto
  .add(.videos([BVVideo()])) //api can handle one BVVideo currently
  .configure(config)
  .add(.submit)
  .handler { result in
    if case let .failure(errors) = result {
      errors.forEach { print($0) }
      return
    }
    guard case let .success(meta, _) = result else {
      return
    }
  }
```

***

### Progressive Submission

This documentation explains how user-generated content (UGC) can be submitted and updated using the [Progressive Submission API](/v1.0-ConversationsAPI/docs/review-progressive-submission).

Progressive submission should be used in scenarios where clients want to display multiple review request forms for a number of items. Additionally, progressive submission supports partial or incremental submissions across different devices.

### Objective-C SDK

#### Objective-C

**Initiating Progressive Submit**

Sending a InitiateSubmitRequest returns the current state of the reviews associated with the products and userId passed in the request. It also returns a unique submissionSessionToken that is used to submit content and update reviews.

> 📘
>
> BVInitiateSubmitRequest object requires a userId or an encrypted User Agent String (UAS), at least one productId, and a locale.

```objectivec
BVInitiateSubmitRequest * initiateSubmitRequest = [[BVInitiateSubmitRequest alloc] initWithProductIds:@[@"product1", @"product2", @"product3"]];
initiateSubmitRequest.userId = @"test109";
initiateSubmitRequest.locale = @"en_US";
 
[initiateSubmitRequest submit:^(BVSubmissionResponse<BVInitiateSubmitResponseData *> * _Nonnull response) {
  // Submission was successfully initiated
} failure:^(NSArray<NSError *> * _Nonnull errors) {
  //Submission initiation failed with errors
}];
```

**Progressive Submission**

Once the initiateSubmitResponse has returned and the SubmissionSessionToken has been received, You can then start to construct a progressiveSubmissionRequest object. The request returns a review object that holds the submitted review fields, and the sessions token that was used in the request.

> 📘
>
> BVProgressiveSubmitRequest object requires a userId and userEmail, or UserToken (User Agent String), productId, locale, submissionSessionToken, SubmissionFields

```objectivec
BVProgressiveSubmitRequest *request = [[BVProgressiveSubmitRequest alloc]
initWithProductId:@"sampleProduct"];
 
request.submissionSessionToken = sessionToken; //”unique session token”
request.locale = locale;  //”user locale”
request.userToken = userToken; //”encrypted user token”
request.submissionFields = fields; //submission field dictionary
 
[request submit:^(BVSubmissionResponse<BVProgressiveSubmitResponseData *> * _Nonnull response) {
  /// Submission was sucessful
} failure:^(NSArray<NSError *> * _Nonnull errors) {
  ///submission failed with errors
}];
```

**Photo Submission**

To submit a photo using `ProgressiveSubmission`, first upload the photo with `PhotoSubmissionRequest`, then add the photo URL to the `SubmissionFields` of the `ProgressiveSubmission`.

```objectivec
BVPhotoSubmission *photo = [[BVPhotoSubmission alloc] initWithPhoto:image
  photoCaption:photoCaption
  photoContentType:contentType];
 
[photo upload:^(NSString * _Nonnull photoURL,
  NSString * _Nonnull photoCaption) {
    //Assign returned URL to photourl field
    fields[@"photourl_1"] = photoURL;
    request.submissionFields = fields
  } failure:^(NSArray<NSError *> * _Nonnull errors) {
    //photo upload failed with errors
}];
```

**Video Submission**

To submit a video using `ProgressiveSubmission`, first upload the video with `BVVideoSubmission`, then attach the video URL to the SubmissionFields of the `ProgressiveSubmission`.

```objectivec
 BVVideoSubmission *video = [[BVVideoSubmission alloc] initWithVideo:@"Video Path"
                                                        videoCaption:@"Test Video"
                                                        uploadVideo:YES
                                                    videoContentType:BVVideoContentTypeReview];
    [video submit:^(BVVideoSubmissionResponse *videoSubmissionResponse) {
        if (videoSubmissionResponse.result) {
            NSString *videoUrl = videoSubmissionResponse.result.video.videoUrl;
            if (videoUrl) {
                NSLog(@"%@", videoUrl);
            }
        }
    } error:^(NSError *errors) {
        // handle error appropriately
    }];
```

<br />

#### Swift

**Initiating Progressive Submit**\
Sending a InitiateSubmitRequest returns the current state of the reviews associated with the products and userId passed in the request. It also returns a unique submissionSessionToken that s used to submit content and update reviews.

> 📘
>
> The initiateSubmitRequest object requires a userId or an encrypted User Agent String (UAS), at least one productId, and a locale.

```objectivec
let initiateSubmitRequest = BVInitiateSubmitRequest(productIds: ["product1", "product2", "product3"])
initiateSubmitRequest.userId = user
initiateSubmitRequest.locale = locale
 
initiateSubmitRequest.submit({ (initiateSubmitResponseData) in
  /// Submission was successfully initiated
}, failure: { (errors) in
  ///Submission initiation failed with errors
})
```

**Progressive Submission**\
Once the initiateSubmitResponse has returned and the SubmissionSessionToken has been received, You can then start to construct a progressiveSubmissionRequest. The request returns a review object that holds the submitted review fields, and the sessions token that was used in the request.

> 📘
>
> The submission object requires a userId and userEmail, or UserToken (User Agent String), productId, locale, submissionSessionToken, SubmissionFields

```objectivec
let submission = BVProgressiveSubmitRequest(productId:"productId")
submission.submissionSessionToken = submissionSessionToken
submission.locale = locale
submission.userToken = userToken
submission.submissionFields = fields
 
submission.submit({ (submittedReview) in
  /// Submission was sucessful
}, failure: { (errors) in
  ///submission failed with errors
})
```

**Photo Submission**\
To submit a photo with a ProgressiveSubmission you will need to attach a photo’s url to the progressiveSubmission’s SubmissionFields after uploading the photo using the ‘PhotoSubmissionRequest'.

```objectivec
let photo = BVPhotoSubmission(
  photo: image,
  photoCaption: photoCaption,
  photoContentType: .review)
 
  photo.submit({ (photoSubmissionResponse) in
    //Assign returned URL to photourl field
    fields["photourl_1"] = photoURL;
    request.submissionFields = fields
 
  }) { (errors) in
    //photo upload failed with errors
}
```

**Video Submission**

To submit a video with `ProgressiveSubmission`, first upload the video using `BVVideoSubmission`, then add the video URL to the `SubmissionFields` of the `ProgressiveSubmission`.

```objectivec
 let video = BVVideoSubmission(video: "Video Path", 
                                      videoCaption: "Test Video",
                                      uploadVideo: true,
                                      videoContentType: .review)
        video.submit({ (videoSubmissionResponse) in
            guard let result = videoSubmissionResponse.result else {
                return
            }
            guard let videoUrl = result.video.videoUrl else {
                return
            }
            print(videoUrl)
        }) { (errors) in
            // handle error appropriately
        }
```

<br />

### Swift SDK

**Initiating Progressive Submit**

Sending a InitiateSubmitRequest returns the current state of the reviews associated with the products and userId passed in the request. It also returns a unique submissionSessionToken that s used to submit content and update reviews.

> 📘
>
> BVMultiProductQuery object requires a userId or an encrypted User Agent String (UAS), at least one productId, and a locale.

```swift
var encodedUAS =
  "926e8604e6094ad98ec63c6eeb8d9e1a5cd47d68b141a8b0a5e206dc7e610504646174653d3230323131323037267573657269643d454d30303126456d61696c416464726573733d6162697368656b68732e6b616d617468253242546573742534306266f6963652ef6d"
let multiProduct = BVMultiProduct(
  productIds: ["product1", "product2"], locale: "en_US", userToken: encodedUAS, userId: nil)
 
guard let initiateMultiproductSubmission = BVMultiProductQuery(multiProduct) else {
  return
}
 
initiateMultiproductSubmission
  .configure(config)
  .handler { response in
    if case let .failure(errors) = response, let error = errors.first {
      print("Fail")
      return
    }
    guard case let .success(_, products) = response else {
      return
    }
    for product in products.productFormData! {
      print(product.review?.productExternalId)
      print(product.submissionSessionToken)
    }
 
  }
initiateMultiproductSubmission.async()
```

**Progressive Submission**\
Once the initiateSubmitResponse has returned and the SubmissionSessionToken has been received, You can then start to construct a BVProgressiveReviewSubmission object. The request returns a review object that holds the submitted review fields, and the sessions token that was used in the request.

> 📘
>
> BVProgressiveReviewSubmission object requires a userId and userEmail, or UserToken (User Agent String), productId, locale, submissionSessionToken, SubmissionFields

```swift
var submissionFields = BVProgressiveReviewFields()
submissionFields.rating = 4
submissionFields.title = "my favorite product ever!"
submissionFields.reviewtext =
  "favorite product review body favorite product review body favorite product review body"
submissionFields.agreedToTerms = true
 
var reviewSubmission = BVProgressiveReview(
  productId: "product1", submissionFields: submissionFields)
reviewSubmission.isPreview = true
reviewSubmission.submissionSessionToken = "sessionToken"
reviewSubmission.locale = "en_US"
reviewSubmission.userToken = encodedUAS
 
guard let progressiveReviewSubmission = BVProgressiveReviewSubmission(reviewSubmission) else {
  return
}
 
progressiveReviewSubmission.configure(config)
 
progressiveReviewSubmission
  .handler { result in
    if case let .failure(errors) = result, let error = errors.first {
      return
    }
 
    if case let .success(_, response) = result {
      print(response)
    }
    print("Success")
  }
 
progressiveReviewSubmission.async()
```

**Photo Submission**\
To submit a photo with a `ProgressiveSubmission`, first upload the photo using `BVPhotoSubmission`, then add the photo URL to the `SubmissionFields` of the `ProgressiveSubmission`.

```swift
let jpg: BVPhoto =
  BVPhoto(caption: "Hello?",
  contentType: .review,
  image: image)
 
let photoSubmission: BVPhotoSubmission =
  BVPhotoSubmission(jpg)
    .configure(config)
    .handler
    { (result: BVConversationsSubmissionResponse<BVPhoto>) in
      guard case .success = result else {
        return
      }
    }
 
photoSubmission.async()
```

**Video Submission**

To submit a video with a `ProgressiveSubmission`, first upload the video using `BVVideoSubmission`, then add the video URL to the `SubmissionFields` of the `ProgressiveSubmission`.

```swift
 let video: BVVideo = BVVideo(URL(filePath: "Video Path"), caption: "Test Video", uploadVideo: true)
        guard let videoSubmission: BVVideoSubmission = BVVideoSubmission(video: video) else {
            return
        }
        videoSubmission
            .configure(config)
            .handler { (response: BVConversationsSubmissionResponse<BVVideo>) in
                if case let .failure(errors) = response {
                    print(errors)
                    return
                }
                guard case let .success(meta, result) = response,
                      let formFields = meta.formFields else {
                    return
                }
                let videoUrl = result.videoUrl
                print(videoUrl)
            }
        videoSubmission.async()
```

### Question submission

Submitting a question is nearly identical to submitting a review, detailed above. Create an instance of BVQuestionSubmission, fill in some parameters, and submit it!

> 📘
>
> A `QuestionSubmission` object requires a `productId` for which this question corresponds to.

### Objective-C SDK

```objectivec
// create question submission and fill out with user-input values
BVQuestionSubmission* question = [[BVQuestionSubmission alloc] initWithProductId:@"test1"];
question.questionSummary = userQuestion; // "Heavy?"
question.questionDetails = userQuestion; // "How much does this weigh?"
question.userNickname = userNickname;    // "Samantha55"
question.userId = userId;                // user's external ID
question.userEmail = userEmail;          // "test@test.com"
question.agreedToTermsAndConditions;  [NSNumber numberWithBool:YES];
 
// submit the question
[question submit:^(BVSubmissionResponse<BVSubmittedQuestion *> * _Nonnull response) {
  // question submitted successfully!
} failure:^(NSArray<NSError *> * _Nonnull errors) {
  // handle failure appropriately
}];
```
```swift
// create question submission and fill out with user-input values
let question = BVQuestionSubmission(productId: "test1")
question.questionSummary = userQuestion // "Heavy?"
question.questionDetails = userQuestion // "How much does this weigh?"
question.userNickname = userNickname // "Samantha55"
question.userId = userId             // user's external ID
question.userEmail = userEmail       // "test@test.com"
question.agreedToTermsAndConditions  = true
 
// submit the question
question.submit({ (questionSubmission: BVSubmissionResponse<BVSubmittedQuestion>) in
  // question submitted successfully!
}, failure: { (errors: [Error]) in
 // handle failure appropriately
})
```

### Swift SDK

```swift
let question: BVQuestion =
  BVQuestion(
    productId: "test1",
    questionDetails: "Does it have fingerprint sensor?",  //
    questionSummary: "Fingerprint Sensor",
    isUserAnonymous: false)
 
guard let questionSubmission = BVQuestionSubmission(question) else {
  return
}
questionSubmission
  .add(.nickname("Nick"))
  .add(.agree(true))
  .add(.submit)
 
questionSubmission
  .configure(config)
  .handler { result in
    if case let .failure(errors) = result {
      // handle failure appropriately
      return
    }
    guard case let .success(meta, _) = result else {
      return
    }
    // question submitted successfully!
  }
questionSubmission.async()
```

***

### Answer submission

Submitting an answer is nearly identical to submitting a review or question. Create an instance of `BVAnswerSubmission`, fill in some parameters, and submit it!

> 📘
>
> An `AnswerSubmission` object requires a `questionId` for which this answer responds to, and `answerText`, which is the body of the answer.

### Objective-C SDK

```objectivec
// create answer submission and fill out with user-input values
BVAnswerSubmission* answer = [[BVAnswerSubmission alloc] initWithQuestionId:userQuestionId answerText:userAnswerText];
answer.userNickname = userNickname; // "Samantha55"
answer.userId = userId;             // user's external ID
answer.userEmail = userEmail;       // "test@test.com"
answer.agreedToTermsAndConditions = [NSNumber numberWithBool:YES];
 
 // submit the answer
[answer submit:^(BVSubmissionResponse<BVSubmittedAnswer *> * _Nonnull response) {
  // answer submitted successfully!
} failure:^(NSArray<NSError *> * _Nonnull errors) {
    // handle failure appropriately
}];
```
```swift
// create answer submission and fill out with user-input values
let answer = BVAnswerSubmission(questionId: userQuestionId, answerText: userAnswerText)
answer.userNickname = userNickname // "Samantha55"
answer.userId = userId             // user's external ID
answer.userEmail = userEmail       // "test@test.com"
answer.agreedToTermsAndConditions = true
 
// submit the answer
  answer.submit({ (answerSubmission: BVSubmissionResponse<BVSubmittedAnswer>) in
  // answer submitted successfully!
}, failure: { (errors: [Error]) in
  // handle failure appropriately
})
```

### Swift SDK

```swift
let answer: BVAnswer = BVAnswer(
  questionId: "1642264", answerText: "Yes. Charger is included in the box.")
guard let answerSubmission = BVAnswerSubmission(answer) else {
  return
}
 
answerSubmission
  .add(.nickname("Nick"))
  .add(.agree(true))
  .add(.submit)
  .configure(config)
  .handler { result in
    if case let .failure(errors) = result {
      // handle failure appropriately
      return
    }
    guard case let .success(meta, _) = result else {
      return
    }
    // answer submitted successfully!
  }
// submit the answer
answerSubmission.async()
```

***

### Review comment submission

Submitting a review comment is as easy as creating a `BVCommentSubmission` object with the default initializer and filling out appropriate properties on the `BVCommentSubmission` object. Look at the sample below for some starter code.

### Objective-C SDK

```objectivec
NSString *commentText = @"I love comments almost as much as Objective-C! They are just the most! Seriously!";
NSString *commentTitle = @"Comments Can We Written In Objective-C";
 
BVCommentSubmission *submission = [[BVCommentSubmission alloc] initWithReviewId:@"192550" withCommentText:commentText];
 
//commentRequest.fingerPrint = // the iovation fingerprint would go here...
submission.action = BVSubmissionActionPreview;
submission.campaignId = @"BV_COMMENT_CAMPAIGN_ID";
submission.commentTitle = commentTitle;
submission.locale = @"en_US";
submission.sendEmailAlertWhenPublished = [NSNumber numberWithBool:YES];
submission.userNickname = @"UserNickname";
submission.userId = @"UserId";
submission.userEmail = @"developer@bazaarvoice.com";
submission.agreedToTermsAndConditions = [NSNumber numberWithBool:YES];
 
// user added a photo to this review
//[submission addPhoto:[UIImage imageNamed:@"puppy"] withPhotoCaption:@"What a cute pupper!"];
 
[submission submit:^(BVSubmissionResponse<BVSubmittedComment *> * _Nonnull response) {
  // success
  [self showSuccess:@"Success Submitting Feedback!"];
} failure:^(NSArray<NSError *> * _Nonnull errors) {
  // error
  [self showError:errors.description];
}];
```
```swift
let commentText = "I love comments! They are just the most! Seriously!"
let commentTitle = "Best Comment Title Ever!"
let commentRequest = BVCommentSubmission(reviewId: "192548", withCommentText: commentText)
 
commentRequest.action = .preview
 
//commentRequest.fingerPrint = // the iovation fingerprint would go here...
commentRequest.campaignId = "BV_COMMENT_CAMPAIGN_ID"
commentRequest.commentTitle = commentTitle
commentRequest.locale = "en_US"
commentRequest.sendEmailAlertWhenPublished = true
commentRequest.userNickname = "UserNickname"
commentRequest.userId = "UserId"
commentRequest.userEmail = "developer@bazaarvoice.com"
commentRequest.agreedToTermsAndConditions = true
 
// Some PRR clients may support adding photos, check your configuration
//  if let photo = UIImage(named: "puppy"){
//    commentRequest.addPhoto(photo, withPhotoCaption: "Review Comment Pupper!")
//  }
 
commentRequest.submit({ (commentSubmission) in
// success
self.showAlertSuccess(message: "Success Submitting Review Comment!")
}, failure: { (errors) in
// error
self.showAlertError(message: errors.description)
})
```

### Swift SDK

```swift
let comment =
  BVComment(
    reviewId: "20134832",
    commentText: "Thanks for posting this review!",
    commentTitle: "Nice Review.")
guard let commentSubmission = BVCommentSubmission(comment) else {
  return
}
 
commentSubmission
  .add(.submit)
  .add(.nickname("Nick"))
  .configure(config)
  .handler { (response: BVConversationsSubmissionResponse<BVComment>) in
    if case let .failure(errors) = response {
      // error
      return
    }
    guard case let .success(meta, result) = response else {
      return
    }
    // success
  }
commentSubmission.async()
```

***

### Feedback submission

Submitting a feedback is the simplest of content submissions. Create an instance of `BVFeedbackSubmission`, fill out the required parameters, and submit it! You can use the Feedback submission for either Helpfulness votes or for flagging inappropriate content, just set the type with the `BVFeedbackType` enumerator.

> 📘
>
> A `BVFeedbackSubmission` object requires a `contentId` which will correspond to the identifier of the Review, Question, or Answer your client is providing feedback on.

> 🚧
>
> You cannot submit feedback for syndicated content. Make sure to check the `IsSyndicated` flag before you display your feedback UI.

### Objective-C SDK

```objectivec
BVFeedbackSubmission *feedback = [[BVFeedbackSubmission alloc] initWithContentId:contentId withContentType:BVFeedbackContentTypeReview withFeedbackType:BVFeedbackTypeHelpfulness];
feedback.userId = userId;
feedback.vote = BVFeedbackVotePositive;
feedback.action = BVSubmissionActionPreview;
 
[feedback submit:^(BVSubmissionResponse<BVSubmittedFeedback *> * _Nonnull response) {
  // success
 
  // Make sure to disable the submission UI so the user can't submit again.
} failure:^(NSArray<NSError *> * _Nonnull errors) {
  // error
  // Ooops, some error. Rollback if needed.
}];
```
```swift
let feedback = BVFeedbackSubmission(contentId: contentId,
  with: BVFeedbackContentType.review,
  with: BVFeedbackType.helpfulness)
 
feedback.userId = userId
feedback.vote = BVFeedbackVote.positive // or .Negative for down vote
 
feedback.submit({ (response) in
  // success
 
  // Make sure to disable the submission UI so the user can't submit again.
 
}) { (errors) in
  // error
  // Ooops, some error. Rollback if needed.
}
```

### Swift SDK

```swift
let feedback =
  BVFeedback.helpfulness(
    vote: .positive,
    authorId: "reviewAuthor",
    contentId: "reviewId",
    contentType: .review)
 
guard let feedbackSubmission = BVFeedbackSubmission(feedback) else {
  return
}
 
feedbackSubmission
  .configure(config)
  .handler { (response: BVConversationsSubmissionResponse<BVFeedback>) in
    if let _ = response.errors {
      // error
      // Ooops, some error. Rollback if needed.
      return
    }
    guard case let .success(_, result) = response else {
      return
    }
    // success
    // Make sure to disable the submission UI so the user can't submit again.
  }
feedbackSubmission.async()
```

# Generic form field options

All available fields are detailed in `BVReviewSubmission.h` and further in [Bazaarvoice's API Documentation](/v1.0-ConversationsAPI/docs/home). Required fields, and specific rules per field (*"reviewText must be longer than X characters"*) is dependent on your specific deployment setup.