okendo
Okendo
Okendo integration for Shogun Frontend.
Okendo helps Shopify retailers build shopper trust and excitement, showcase customer experiences and compel buying action.
⚠️ | This package runs on Shogun Frontend and is in customer Beta. It might not currently support all ecommerce platforms or cover all use cases. |
Overview
Users of Shogun Frontend with Shopify stores can leverage this package to display individual and aggregate reviews from Okendo, and submit new reviews to Okendo.
Installation
yarn add @frontend-sdk/okendo
npm install @frontend-sdk/okendo
Submit review
Usage
Call getOkendoReviewSubmissionUrl()
with your Okendo subscriber ID and a Shopify product ID. It will return a URL hosted by Okendo, where a new review can be entered.
Create a custom button that, when clicked, takes the user to this review submission URL.
Example
import { getOkendoReviewSubmissionUrl } from '@frontend-sdk/okendo'
const SubmitReviewPage = () => {
const subscriberId = 'abcde123-456f-ghi8-9jkl-0123mnop4567'
const productId = '612345678901'
const submissionUrl = getOkendoReviewSubmissionUrl(subscriberId, productId)
const handleClick = () => {
window.open(submissionUrl, '_blank')
}
return (
<div>
<button onClick={handleClick}>Click here to go to submit review page</button>
</div>
)
}
How to find Okendo subscriber ID
Your Okendo subscriber ID can be found in Okendo's admin portal (https://reviews.okendo.io/admin) in Settings → Integrations → User ID. The User ID is your subscriber ID.
Product review aggregate
Usage
Call useOkendoProductReviewAggregate()
with your Okendo subscriber ID and a Shopify product ID. Destructure the result into reviewCount
, reviewCountByLevel
, reviewRatingValuesTotal
, and status
.
reviewCount
: Total number of reviews
reviewCountByLevel
: Number of reviews per rating
reviewRatingValuesTotal
: Sum of all ratings
status
: status of the request to Okendo's API: success | fail | pending
Create your own component(s) to display the above data as you would like. To get the average rating, divide reviewRatingValuesTotal
by reviewCount
.
Example
import { useOkendoProductReviewAggregate } from './use-okendo-product-review-aggregate'
export const ProductReviewAggregate = ({ subscriberId, productId }) => {
const { reviewCount, reviewCountByLevel, reviewRatingValuesTotal, status } = useOkendoProductReviewAggregate({
subscriberId,
productId,
})
const averageRating = (reviewRatingValuesTotal / reviewCount).toFixed(2)
return (
<div>
<h2>Status of fetching reviews: {status}</h2>
<StarRating rate={Number(averageRating)} />
<h3>Average rating: {averageRating} / 5</h3>
<h3>Number of reviews per rating:</h3>
<div>
{Object.entries(reviewCountByLevel).map(([key, value], i) => (
<div key={i}>{`${key.slice(5, 6)} star: ${value}`}</div>
))}
</div>
<h3>Total number of reviews: {reviewCount}</h3>
</div>
)
}
const StarRating = ({ rate }) => {
const width = `${(rate * 100) / 5}%`
return (
<div style={css.starRating}>
<span style={css.starRatingA11yText}>Rated {rate.toFixed(2)} out of 5</span>
{/* Use width to show only the percentage of the fiveFilledStarsImage that matches the rating */}
<div style={{ ...css.starRatingActive, width }} />
</div>
)
}
const css = {
starRating: {
position: 'relative',
width: '75px',
height: '15px',
overflow: 'hidden',
},
starRatingA11yText: {
display: 'none',
},
starRatingActive: {
position: 'absolute',
height: '100%',
backgroundImage: fiveFilledStarsImage,
backgroundSize: '75px 15px',
filter: 'brightness(0)',
},
}
const fiveFilledStarsImage =
"url('data:image/svg+xml;charset=UTF-8, %3Csvg%20width%3D%2280%22%20height%3D%2214%22%20viewBox%3D%220%200%2080%2014%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22%23FFB829%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M71.996%2011.368l-3.94%202.42c-.474.292-.756.096-.628-.443l1.074-4.53-3.507-3.022c-.422-.363-.324-.693.24-.74l4.602-.37%201.778-4.3c.21-.51.55-.512.762%200l1.78%204.3%204.602.37c.552.046.666.37.237.74l-3.507%203.02%201.075%204.532c.127.536-.147.74-.628.444l-3.94-2.422zM55.996%2011.368l-3.94%202.42c-.474.292-.756.096-.628-.443l1.074-4.53-3.507-3.022c-.422-.363-.324-.693.24-.74l4.602-.37%201.778-4.3c.21-.51.55-.512.762%200l1.78%204.3%204.602.37c.552.046.666.37.237.74l-3.507%203.02%201.075%204.532c.127.536-.147.74-.628.444l-3.94-2.422zM40.123%2011.368l-3.94%202.42c-.475.292-.756.096-.63-.443l1.076-4.53-3.508-3.022c-.422-.363-.324-.693.24-.74l4.602-.37%201.778-4.3c.21-.51.55-.512.762%200l1.778%204.3%204.603.37c.554.046.667.37.24.74l-3.508%203.02%201.075%204.532c.127.536-.147.74-.628.444l-3.94-2.422zM24.076%2011.368l-3.94%202.42c-.475.292-.757.096-.63-.443l1.076-4.53-3.507-3.022c-.422-.363-.324-.693.238-.74l4.603-.37%201.78-4.3c.21-.51.55-.512.76%200l1.78%204.3%204.602.37c.554.046.667.37.24.74l-3.508%203.02%201.074%204.532c.127.536-.146.74-.628.444l-3.94-2.422zM8.123%2011.368l-3.94%202.42c-.475.292-.756.096-.63-.443l1.076-4.53L1.12%205.792c-.422-.363-.324-.693.24-.74l4.602-.37%201.778-4.3c.21-.51.55-.512.762%200l1.778%204.3%204.603.37c.554.046.667.37.24.74l-3.508%203.02%201.075%204.532c.127.536-.147.74-.628.444l-3.94-2.422z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E')"
Product reviews
Usage
Call useOkendoProductReviews()
with your Okendo subscriber ID and a Shopify product ID. You can pass params
as an optional third argument to useOkendoProductReviews
if you wish to receive fewer or sorted reviews. Destructure the result into reviews
and status
.
reviews
: list of reviews
status
: status of the request to Okendo's API: success | fail | pending
Create your own component(s) to map through the list of review data, and display it as you would like.
Optional params
params
: takes a query string that can include:
limit
: integer 1 - 25orderBy
:has_media desc
|has_media asc
|date desc
|date asc
|rating desc
|rating asc
|helpful desc
|helpful asc
For example: limit=6&orderBy=rating%20desc
Example
import { useOkendoProductReviews } from './use-okendo-product-reviews'
export const ProductReviews = ({ subscriberId, productId, params }) => {
const { reviews, status } = useOkendoProductReviews({ subscriberId, productId, params })
return (
<div>
<h2>Status of fetching reviews: {status}</h2>
<h1>Product Reviews:</h1>
{reviews.map((review) => (
<div key={review.reviewId} style={{ border: '3px solid black', marginBottom: '16px', padding: '16px' }}>
<h3>{review.title}</h3>
<img src={review.productImageUrl} alt={review.productName} />
<div>{review.productName}</div>
<div>Rating: {review.rating} / 5</div>
<div>{review.body}</div>
</div>
))}
</div>
)
}
Updated over 1 year ago