Limits and guarantees¶
Review Requests emails your customers and prints a claim about them on your product pages. Both are things you are answerable for, so this page writes out exactly what the extension promises, what it leaves to OpenCart, and what it will not do on your behalf.
At a glance¶
| If you are asking | The short answer |
|---|---|
| Does a refund take the badge off a review? | No. The request is flagged Order refunded since and joins Needs a look; whether the review stays is yours to decide. More |
| Will the badge show on a customised theme? | Not necessarily. A review template the anchor does not fit gets no badge and no disclosure line, silently; the checklist is where you find out. More |
| Does uninstalling delete my requests or the suppression list? | No. Every table stays. The badge and the disclosure line leave your product pages, and the reviews stay. More |
| Does approving a review move the star average on OpenCart 4.1? | No. That is core's Sync button on Catalog → Reviews. More |
| Is a failed send retried? | Never automatically. The row says Send failed with the error, and Resend is yours to press. More |
| Does retention delete the request records? | No. It empties the address, the link and any send error and keeps the row, because the badge is joined through it. More |
| Does it notice bounces? | No. Nothing reads a mailbox, so a dead address is asked again the next time it qualifies. More |
| Can the API send a request or read the suppression list? | No. It only reads, and the suppression list is not one of its resources. More |
| Do guests earn Loyalty points for a review? | No. Points need a customer account behind the review, and are paid only when you approve it. More |
| Does my reply to a review show on every theme? | Only where the review template prints the review's text as core does. Where it does not, the reply is saved and nothing prints; the checklist says so. More |
What the verified-purchase badge means¶
Verified at the time of writing. The badge says this review was written by somebody who was emailed a link because they had bought that product on an order that reached the status you chose. It does not say the sale is still standing today.
- A refund does not strip the badge. The review was written by a real buyer and it still was. What happens instead is that the request grows an Order refunded since flag, the row joins the Needs a look count on the Requests tab, and you decide whether the review should stay. If you want it gone, that is Catalog → Reviews, the same as any other review.
- The badge and its disclosure line are one switch. Turning the badge off takes the disclosure line with it, because a disclosure explaining a verification nobody can see is worse than neither.
- Removing the extension leaves the reviews and takes the marking. Core's reviews are core's: uninstalling Review Requests does not delete one. But the badge is spliced into the review list by this extension, and so are the disclosure line beneath it and your replies under the reviews, so a product page that carried them carries none of them afterwards, while the reviews stay. The replies themselves stay in this extension's own table and print again if you install it again. Whatever your product pages claim after that point is yours to be right about.
- A heavily customised theme may carry no badge at all. The badge is spliced at one anchor in your store's review template, and a template the anchor does not fit exactly once is left exactly as core rendered it: no badge, no disclosure line, and no error anywhere. The storefront stays silent about it on purpose; the Before anything is sent checklist on the Settings tab is where you find out, and it answers for the template your store actually renders rather than for core's.
Leaving products out of requests¶
Never ask about these products and Never ask about these categories are for what nobody reviews: gift cards, samples, services.
- They are read when a request is sent, not when the order is found. A product you add to either list drops out of every request still waiting, and out of a reminder whose request has already gone. Taking it off the list again puts it back into any request not yet sent; a product already left out of a request that went stays that way.
- A category takes every subcategory beneath it, and a product in any excluded category is left out whichever other categories it is also in.
- An order with nothing else on it is not asked at all. The row says Not asked, the same as an order whose every product has since been deleted.
- Nothing already reviewed changes. A review written before you added the product keeps its badge, and Loyalty points are paid for an approved review whatever the lists say. The lists decide who is emailed and nothing else.
- The order still records everything that was on it. A product left out is kept on the request, marked as left out of requests, on the Requests tab, on the page the email's link opens and through the API.
- The initial collection's count is an upper bound. Its arithmetic counts orders, and does not subtract an order whose every product you have left out. Such an order is marked Not asked when its turn comes, so the count can be higher than the emails that go out, never lower.
Sending hours¶
Send from (hour) and Send until (hour) keep requests, reminders and an initial collection's emails inside the hours you choose. 0 to 24, the default, sends at any hour.
- Outside the hours, passes still run. They find new orders, re-check reviews and shed old addresses, and send nothing. What waited goes out in the first pass after the hours open, under the same daily limit as everything else.
- Every way of starting a pass obeys them: your store's cron, the command-line door and Run a pass now, which says the hours are closed rather than sending.
- The hours are read in one timezone for the whole installation, the one on the default store's settings. OpenCart has one timezone per installation and its store form has no timezone field, so a second storefront serving customers abroad sets its hours shifted into that shared zone.
- Fewer open hours is fewer emails a day. One pass sends at most 50, so with an hourly pass a daily limit above 50 times the number of open hours cannot be reached.
- A closed hour is not a failure. The pass ends completed with nothing sent, and the checklist does not treat a quiet night as a stopped schedule.
Replies to reviews¶
Your reply to a review is written on core's own Catalog → Reviews form, in a Reply box under the review's text, and printed under that review on the product page, headed Response from the store.
- Any review, not only the ones collected here. A reply is the store speaking, not a verification claim.
- No anchor, no reply. The reply is printed after the review's text, where core's review template prints it. A theme whose review template does not print it that way exactly once gets no reply on the page, silently, the same way it gets no badge. The reply is still saved. The Before anything is sent checklist says whether your store's template has a place for it, once you have written one.
- The same rule holds on the form. If an installed modification has reshaped core's review form so the box has nowhere to go, the form stays core's own, no reply box appears, and this extension's log says so.
- Turning the badge off does not hide replies. Show the verified-purchase badge governs the badge and its disclosure line only.
- Plain text, up to 1,000 characters, which is core's own bound on a review. Line breaks are kept; anything that looks like HTML is shown as the characters you typed. A longer reply is cut at 1,000 and the log says so.
- Emptying the box removes the reply. Deleting the review removes its reply with it. On 4.0.2.x, deleting a product deletes its reviews without telling any extension, so their replies are left in the table, where nothing ever prints them again.
- Anybody who can edit reviews can reply. There is no permission of its own: whoever may modify Catalog → Reviews writes the replies, and the log records which admin user saved or removed one, never what it said.
- What it adds to a product page is bounded. Core's review list shows five reviews a page, so at most five replies of up to 1,000 characters, plus a few dozen characters of markup each, and nothing at all on a product with no replies.
What OpenCart does, that this extension does not fix¶
These are core behaviours. They are here because each one will be read as this extension's bug the first time you meet it.
- Approving a review on OpenCart 4.1 does not change the product's star average — that needs the Sync button on Catalog → Reviews. This is core behaviour, not something this extension can do for you. The Requests tab says the same sentence beside your requests, on 4.1 and up only: 4.0.2.0 computes the average from the review rows every time, so there is nothing to sync there.
- OpenCart 4.1.0.4 cannot run a scheduled task at all. Its
cron.phpcrashes inside OpenCart nineteen lines before any extension is reached, so every scheduled job on the store stops: this extension's hourly pass, and every other extension's. Nothing here repairs it and nothing here refuses to install over it: everything you do by hand works, and one crontab line running this extension's own door runs the hourly pass exactly as the scheduler would have. The settings screen names your release and gives you the command. - Deleting a product deletes its reviews. OpenCart removes a product's reviews along with the product and tells no extension it did. Requests that had collected one of them grow a Review no longer exists flag at the next pass, which is usually a deleted product rather than anything wrong.
- Every review collected here carries
customer_id = 0, including reviews from customers who have an account. Core's own model takes that column from whoever is logged in, and the person following an emailed link is nobody. It changes nothing you can see: the badge, and who earns Loyalty points for the review, are both joined through this extension's own record of the order, never through that column. It is written down because a database export shows it. - On 4.0.2.0,
oc_review.date_modifiedstays at zero for every review submitted through a storefront, because core's insert on that release does not set the column at all. Reviews collected here go in through that same insert, so they look like every other storefront review on that store. - A review submitted through a request link is accepted whether or not Allow Guest Reviews is on. That setting guards core's own form on the product page. A request link is not that form: the person holding it has already been matched to an order, which is a stronger check than the setting makes. Your store's Allow Reviews setting is a different matter: with reviews switched off store-wide, nothing is sent at all.
- One alert email per collected review lands in your inbox if you have
ticked Review under System → Settings → Mail → Alert Mail. Reviews
collected here are written through core's own model, which fires core's own
alert, and that is deliberate: silencing it would mean writing to
oc_reviewbehind core's back. Keep it in mind before you start an initial collection over two thousand orders.
What the design will not do¶
- Retention never deletes a request record. When the retention window elapses, the customer's email address, the request token and any stored send error are blanked and the row is marked purged. The row itself stays for good. It has to: the verified-purchase badge is a join through that row, so deleting it would strip badges off your product pages the day the window elapsed, with the disclosure line still standing beside them, explaining a verification that no longer renders. Keeping the row also means a later initial collection cannot re-ask a customer whose record was tidied away.
- The flags on the Requests tab are up to one pass out of date, and on a store with more collected reviews than one pass re-checks, several passes. Nothing is emailed on either side of a flag, so what the staleness costs is a screen rather than a customer.
- A request whose recipient has just unsubscribed still reads Upcoming until a pass reaches it. Suppression is checked when the email would be sent, not when the list is edited, so the row changes to Unsubscribed at that point. Nothing goes out in between.
- A status change with no
oc_order_historyrow is not one this extension considers to have happened. Orders are found by reading the tail of that table, so an order whose status was changed directly in the database, or by something that writesoc_orderwithout writing a history row, is never picked up. Every ordinary route through OpenCart's own admin writes one. - A failed send is never retried automatically. Your mail engine throwing is not proof that nothing was sent: an error can arrive after the server has already queued the message, and a retry would then be a second email to somebody who has one. The row says Send failed and carries the error, and the Resend button is yours to press once you know what happened. A send that was interrupted mid-flight (a pass killed between the claim and the answer) counts as asked and carries no button at all, for the same reason.
Unsubscribing¶
- Following an old unsubscribe link can land on a page that says the link is too old, and that is not a failed opt-out. A request link stops resolving once the retention window has emptied its request, and anybody holding a link that old has by construction had nothing from us since: suppression only ever stops a future request, and a future request carries its own live link. The page says so and offers the contact route, and you can add any address to the suppression list by hand on the Suppression tab.
- Somebody who unsubscribes can still finish the review they were writing. Opting out stops future requests; it does not close the forms in the email they already have. This looks like a bug the first time you see it, but it is what anybody halfway through writing a review would want.
- Somebody who unsubscribed can take it back from the same link. The page their footer link opens offers Send me review requests again, and pressing it removes their address from the suppression list for that store. Nothing tells you it happened except the list itself.
- The email carries no
List-Unsubscribeheader. OpenCart's mail library exposes no way to set one, so the footer link is the whole of the opt-out. It confirms with a button rather than acting on the link being opened, because a link scanner or a prefetching mail client would otherwise take somebody off your list without either of you knowing.
Addressing, links and mail¶
- The web address in the email comes from the store the order belongs to.
For any store you added yourself, that is the URL on System → Settings →
Stores; for the default store it is a constant in the store's
config.php, which no admin screen can change. A store whose address is blank, or which does not say whether it ishttp://orhttps://, is skipped rather than mailed, because a link that warns the customer before it works is worse than a request that waits. The checklist names the store and the address it read. - Request links are
index.php?route=URLs and are not SEO-rewritten, which is what core's own order emails do. The rewrite needs machinery that only a storefront page load has, and nothing scheduled has one. - Product thumbnails in the email disappear silently on a store with no GD
extension or an unwritable
image/cache/directory. The email goes out with the cards and their links intact and no picture, so the customer who is waiting for it still gets it. - A second store follows the default store until you configure it. Every setting is per store, but a store whose tab you never saved has none of its own: it runs on the default store's, the way OpenCart itself reads a store's settings, and its tab shows them. Saving its tab gives it its own answers, which it keeps from then on, across updates too. Status still comes back off after an update, so a store following the default one sends nothing until you switch it on.
- A deleted store leaves its old orders unaskable. Passes run per store, so orders belonging to a store row that no longer exists are never picked up again, including by an initial collection. There is nowhere to send them from.
- Deliverability is yours. SPF, DKIM and whatever reputation your sending domain has decide whether these emails land in an inbox, and none of it is visible from inside OpenCart. Your host's own outbound cap is the real ceiling, and it is usually well below the daily limit on the settings screen. A store that hits that ceiling looks to this extension like a successful send. Get both right before you start an initial collection over a back catalogue.
The API, and what it can read¶
Off until you switch it on, under API on the settings screen, and while it is
off every route answers as though this extension had no API at all. Two read
resources: ask is one order asked for a review, with a line per product on it
and the review each one collected; run is one pass of the sending machinery.
The API is generated from what the extension actually
answers.
- It only ever reads. Nothing can send a request, write a review, unsubscribe anybody or add an address to the suppression list through it. A resend and an acknowledgement are judgements about one customer, and they stay on your own screen where the record of who made them is kept.
- The suppression list is not readable through it. It is the audience (every address that asked you to stop), and the credential below cannot be narrowed to one extension, so it is deliberately not a resource.
- The credential is OpenCart's own API user, and it is not scoped. One is enough to read every extension's API on the store and core's own order API besides, across every storefront in the installation. Restrict it by IP address under System → Users → API, and treat it the way you would treat an admin login.
- Contact addresses come back in full, because the address is what the request was sent to and what a suppression is keyed on. There is no redacted mode; there would be nothing to protect from a credential that already opens everything.
- An erased request is still readable and says so. Erasure here empties the
row and keeps it (see what the badge means
for why), so an erased request comes back with
purgedset and its address blank, which is how erased stays distinguishable from never captured. - One thing an incremental sync cannot see. You can ask for every request changed since a moment, and every change this extension makes moves that stamp, the erasure included. What does not move it is OpenCart approving a review, because that happens in core's own Catalog → Reviews screen and touches nothing this extension owns, so a request can go from Waiting to be checked to On the site without an incremental read noticing. Re-read the waiting ones, which is a short list, or walk the whole collection periodically. The API's own page says the same thing in the same words.
- Replies are not readable through it. A reply is on your product page and on core's review form, and nowhere else.
- Nothing records that anybody read anything. No read log, no per-credential audit trail, no rate limiting.
What it does not do at all¶
- No photo or video reviews, no store or service reviews. What is collected is core's review (a rating, some text and a name), because that is what your theme already displays and what your moderation queue already holds.
- Nobody is emailed when you reply. The reviewer finds your reply on the product page or not at all.
- No syndication. Nothing is published to Google, Trustpilot or anywhere else.
- No bounce handling. Nothing reads a mailbox, so an address that hard- bounces is asked again the next time it qualifies.
- No review gating, in any form, ever. There is no setting that asks a customer how they feel first and only invites the happy ones onwards. That is a permanent position rather than a missing feature.
- Nothing is deleted on your behalf beyond two things. Each pass trims the pass log to the newest Keep this many passes records for that store (20 unless you change it). And a suppression goes when you remove it on the Suppression tab, or when the person it belongs to presses Send me review requests again on the unsubscribe page. Everything else is emptied rather than deleted: the erase on Customers → Personal Data and Customers → Remove everything held about a person do what retention does, for one person or for everybody, and neither touches the suppression list. The tables this extension creates are never dropped, including when you uninstall it. See the changelog for what an update keeps, what this holds about a person for what an erasure empties, and reference for the tables themselves.
OpenCart 4.0.2.3: no review can be left at all¶
On that release OpenCart's own review form loads a file that release does not have. A shopper who writes a review and presses Continue is told the model could not be loaded, and nothing is saved, whether they arrived from one of Review Requests' emails or found the product themselves.
- Nothing here looks broken, which is why this section exists. The requests send, the link opens, the product page renders, reviews already on the store still show, and the badge is still right about them.
- What does not work is the one thing the email asks for. While you are on 4.0.2.3, consider pausing the requests: they ask customers to do something the store will not let them do.
It is OpenCart's, not ours: it is the only place in that release's storefront that names the missing file, and the same submission on a bare 4.0.2.2 or 4.1.0.0 store is accepted. No extension can repair it, which is why 4.0.2.3 is not one of the releases Review Requests claims. OpenCart fixed it in 4.1.0.0.
OpenCart 4.1.0.1: a guest cannot complete an order¶
That release reads two fields out of its own guest-checkout form that the form never sends, prints a PHP warning ahead of its reply, and leaves the browser unable to read the reply, so a guest who presses Continue sees nothing happen and never places the order.
- There is no order for a request to follow. Review Requests is whole here and has nothing to work on for guests.
- Customers with an account are unaffected, and every request following one of their orders behaves normally.
It is OpenCart's, not ours; the same press on a bare 4.1.0.0 or 4.1.0.2 store works. 4.1.0.1 is not one of the releases Review Requests claims. OpenCart fixed it in 4.1.0.2.
Loyalty points¶
Points for an approved review pays through the Loyalty extension, and does nothing at all while that is not installed.
- It pays for any approved review with an account behind it, not only the ones collected here. A review a logged-in customer typed into the form on the product page earns for that customer. A review collected through a request link earns for the customer account that placed the order.
- A guest earns nothing, because a guest order has no account to pay into, and neither does a review you add yourself on Catalog → Reviews, which core stores against no customer.
- Paid on approval, once. Submitting earns nothing; approving the same review again, or saving it again after an edit, pays nothing more.
- It never stands in the way of an approval. If Loyalty refuses or fails, the review is still approved and the reason goes to this extension's log.
- The amount is the one set for the customer's own store, the store their account belongs to, rather than the store whose product was reviewed.
Language¶
Review Requests talks to your customers through a request email, the page its link opens, and the disclosure beneath your review list, so what language those are in is a question about your shoppers before it is a question about your admin. Both halves are answered, and counted, on the shared language promise page.
Three things, and the first matters most:
- A shopper reads your own sentences in whatever language you wrote them, and ours only in a language we ship. The ten wording fields are yours, held against the language code your store is registered under, and nothing about translation touches them: write Dutch there and a Dutch customer reads your Dutch. What surrounds them (the buttons, the star row, the labels on the review form) is ours, and a store whose language we ship nothing in reads those in English. So a page can be your words in one language and our words in another. That is deliberate: the merchant's own sentence takes priority over a page in one consistent language.
- Every word of ours is translated as far as somebody has read it and no further, and the rest is English. A string a named reviewer has signed off is served in the language asked for; a string nobody has read is served in English rather than blank or as its own identifier; and a string whose English has since been reworded goes back to English until it is read again. Which string is in which state is on that page, per language, counted rather than claimed, and the email a customer gets is read down the same three states as the page they land on.
- Your wording, your suppression list and your settings are yours, and an
update does not reach them. They are your store's data, saved per store and
per language, and every release leaves them exactly where they are. Editing our
.phpfiles underextension/is a different act: an update replaces those files and takes your change with them, which is what the wording fields exist to spare you.
Anything not described here should be assumed absent. If a behaviour matters to your store, ask before you buy rather than after.