Step 2: Building out Custom Collection Pages


In order to build out a Custom Review Collection experience, all Collection Pages will interact with the Yext Review Submission APIs.

Review Submission API - Endpoint Overview

There are three Review Submission endpoints which will be most relevant for building out a Custom Review Collection experience.

Endpoint Description URL
Review Submission: Create Creates a new First Party Review POST{accountId}/reviewSubmission
Review Submission: Update Updates an existing First Party Review PUT{accountId}/reviewSubmission/{apiIdentifier}
Review Submission: Delete Sets the status of an existing First Party Review to REMOVED DELETE{accountId}/reviewsSubmission/{apiIdentifier}

Creating an App

The first thing you’ll want to do is create a new app in the Developer Console and grant access to the Review Submission Content Delivery API. This permission will grant you access to create, update, and delete reviews. You will be exposing this API Key on your client-side pages, so it’s best practice to only provide this permission for this specific App.

Creating a Review

In order to create a review, the page needs to make a request to the Review Submission: Create endpoint. All of the required fields must be included in the body of the request. How this information is collected is up to the business; most forms will simply have fields for the user to provide all of the required information, and clicking some “Submit” button will result in an API request to the aforementioned endpoint.

Handling the API Response

The Review Submission: Create endpoint handles the requests, but does not create the review synchronously. As such, the endpoint cannot return a Review ID, since the review resource will not have been created yet. If the request is successful, the endpoint will return a 202 Accepted Response, along with an apiIdentifier. The apiIdentifier is a unique value which is either the invitationUid passed as part of the request, or a newly generated UUID. This identifier will be 1:1 with the resulting review, and will be required in order to Update or Delete the created review.

If there are any validation issues with the message, the endpoint will return a 400 Error, which the page can handle and display to the user for resolution; for example, if the email address provided is invalid, the system will return a corresponding error, and the page could display this to the user.

Updating & Deleting Reviews

We encourage developers building out Custom Review Collection Experiences on top of Yext to support updating and deleting reviews by their end-users. There are typically two scenarios in which a user may want to update or delete their review:

  1. The user submits a review, and immediately wants to make an update or delete the review they posted. This scenario is common if the user made a mistake in the content they submitted (wrong email address, for instance), or if the user simply changes their mind about the review.
  2. A business responds to a review, and the end-user decides that they would like to update or delete the original review. This scenario is common if a consumer leaves a negative review, but the business’s response addresses the issue, and the end-user wants to update or delete the review since the business is working toward resolving the issue.

When building out Custom Review Collection experiences, a developer may need to solve for these two scenarios differently.

example edit

Immediate Updates

Because reviews submitted via the Reviews: Create are not available immediately in Reviews: Get or Reviews: List requests, developers who want to support immediate updates will need to store the content of the review on the client-side browser.

As discussed in the Creating a Review section, the Create endpoint of the Review Submission API will return a field called apiIdentifier, which is required as a path parameter for any requests to Update/Delete reviews.

immediate edits

Since the apiIdentifier is returned by the API, the developer will simply need to persist this value on the front-end, so that any subsequent requests triggered by the end-user’s action can contain this value.

Non-Immediate Updates

The other scenario which a business may want to support is the ability for a user to edit or delete their review at some point in the future. As with the immediate update case, the key to supporting this experience is accessing the apiIdentifier.

However, in this scenario, it’s unlikely that the developer has the review content on-hand, so it is a bit trickier to display a clear editing experience to the end-user, who would expect to see the review they left and be able to edit it from the page. As such, the developer will likely need to make a request to fetch the review from Yext.

For the client-side fetch of a review, the developer will want to use Streams API (this would require adding additional permissions to the App). The page should make a request to the relevant Streams API and filter on the apiIdentifier field to grab the review, then display this content to the end-user. After the user updates or deletes their content, the page can make the request to the relevant endpoint and pass the apiIdentifier.

Please note that the review in question will need to have the LIVE status in order to be returned by Streams API. If the review is still QUARANTINED, it will not be returned by Streams API.

This scenario may seem a bit abstract, so let’s consider some real examples.

Example Use Case - Notifying a Reviewer of a Review Response

Imagine a business wants to send an email to reviewers once the business has posted a response, and provide a link to edit the review.

  1. The code should listen to the Reviews Webhook for REVIEW_COMMENT_UPDATED messages.
  2. When the server listening to webhooks get a message of this type for a First Party Review, the code could grab the authorEmail and send an email notifying the consumer that the business has replied to the review
    • This email would include a URL to the Review Collection Page for the relevant entity. The apiIdentifier would likely need to be included as a query parameter on the URL
  3. When the user clicks the page, the page would recognize that there is an apiIdentifier query parameter, and make a request to fetch the review data from Streams API, then render the edit experience to the end-user
  4. The user would make any updates, and the page would send any subsequent requests to the relevant endpoint (Update or Delete)

From the perspective of the Review Collection Page, the responsibility is to check for an apiIdentifier query parameter, and if this parameter exists, fetch the review data, and display an editing experience to the user.

Example Use Case - User Receives Invitation, Leaves Review, Navigates Back to URL Later

Imagine that a consumer received a review invitation email. The user clicked that email, which redirected them to your collection page with the invitationUid query parameter included in the URL. The user left a review. At some point in the future, the end-user transacted with your business again, and decided to update their review.

  1. End-user searches their email inbox and find the original review invitation.
  2. End-user clicks the link in the email to update their review
    • At this point, the user is navigating back to the same URL with the invitationUid query parameter in the URL. If a review has been created using this invitationUid, the apiIdentifier of that review will be that invitationUid (recall that apiIdentifier = invitationUid if invitationUid is passed in the review creation request). So, the system would want to fetch the review with apiIdentifier = invitationUid.
  3. Page grabs invitationUid value from URL, makes request to fetch the review data from Streams API (with apiIdentifier = invitationUid), then renders the edit experience to the end-user with that review data
  4. The user makes any updates, and the page sends any subsequent requests to the relevant endpoint (Update or Delete)

If you wish to support this use case, it may be best to always check the URL for an invitationUid query parameter, and, if it exists, make a request to Streams API to fetch the corresponding review. If no review is returned, the page would render the Create Experience, and if a review was returned, the page would render the Edit Experience.

non immediate updates

Note: Requiring the apiIdentifier to update or delete a review is more secure than allowing the client to pass the Review ID. Review IDs are incremental, so if we accepted the Review ID, an attacker could grab that ID from the page and increment/decrement the ID in subsequent requests to update and delete reviews at will. Since the apiIdentifier is a generated UUID, we avoid this risk.

Fetching Reviews via Streams API

As discussed in the Non-Immediate Updates section of the Collection Pages guide, supporting this use case requires making a request to Yext to fetch reviews from the client-side. The Streams API is a customizable, low-latency, consumer-grade API which can be used for exactly this use case.

Streams API allows a user to configure the specific data they want to receive, as well as the fields within the API which should be indexed, such that the user can query on those fields. For the Collection Page use case described above, it will be crucial to filter on the apiIdentifier field.

Rather than require manual configuration for this use case, we have created this app which contains the configuration for the relevant Streams Endpoint. The ID of the Streams Endpoint which will be created is reviewsStreamsEndpoints_reviews. The following is a sample request: