Skip to content

Limits and guarantees

Back In Stock takes an email address from somebody who cannot buy what they came for, and mails that address once, when they can. This page sets out what that promises and where the promise stops. It is the page to read before you buy, and the page to send a customer's question to afterwards.

Everything here is deliberate. Where a limit exists because of how OpenCart itself works, that is said rather than implied.

At a glance

If you are asking The short answer
Does anything send if no scheduler is set up? Only the first batch after a product save or an order change that puts stock back. Every later batch waits for the sweep, and nothing else calls it. More
Does a restock mail the whole waiting list at once? No. One alert per unit on hand by default, oldest first, with an hour between batches. 0 alerts per unit mails everybody at once. More
Can confirmed opt-in be switched off? No. Nobody is sent an alert until they click the link in the confirmation email, apart from a signed-in customer using their own account address. More
Can a shopper watch "any size"? No. A watch names one product or one option value, and a combination of two unavailable options cannot be watched at all. More
Is there rate limiting on the form? No, and none is planned. What stands in front of it is your captcha, a hidden trap field, a 15-minute wait between confirmation emails to one address, and confirmed opt-in. More
Does shortening a retention period reach people already waiting? No. Each person keeps the period printed in the notice they read. More
Can I export the subscriber addresses? Not from any admin screen. The API, off until you switch it on, can read the waiting list. More
Does uninstalling delete the waiting list? No. All six tables stay. Removing what is held about people is a separate screen, and it cannot be undone. More
Does it work on OpenCart 4.1.0.4? Yes, but OpenCart's own scheduler is broken there. Use the sweep web address or the command line. More

What a watch is

  • A watch names one product, or one option value of it. Back In Stock calls that pair a counter, and a counter is the smallest thing anybody can be alerted about. It is the same split OpenCart itself keeps: one quantity on the product and one on each option value.
  • "Any size" is not one watch. Somebody who wants to be told about Medium, Large and Extra Large signs up three times and confirms three times. Each of those three watches then makes a true claim about one size.
  • A combination of two unavailable option values is not watchable at all. Where Medium is gone and Forest is gone, the form is withheld and the page says so: an alert reading Medium is back while Forest still is not would be a false claim, and there is no accurate way to write it. Pick a size that is out of stock in a colour the store has, or the other way round.
  • The form is not offered until an option is selected. No selection is no counter, and a form that resolved on submit against whatever happened to be selected is how somebody gets mailed about a size they never asked about.
  • A guest is not recognised on return. The product page has no idea who is looking at it and does not guess: recognising a returning shopper would need a cookie the consent notice never mentioned. Signing up again for something already confirmed changes nothing and sends nothing. Signing up again while the first sign-up is still unconfirmed sends a fresh confirmation email, but not within 15 minutes of the last one.
  • A watch is answered once. After the alert is sent the watch is finished; asking again from the product page is a new watch, with a new confirmation email. This is also why an oscillating stock level cannot mail the same person twice.
  • A watch naming no option value can mail twice if the product gains metered variants afterwards. Somebody who signed up for a plain product before its sizes were given their own stock figures is waiting on the product-level counter, and a restock that fills both can send one mail for each. Nothing is lost; two mails arrive instead of one.
  • A product save that drops OpenCart's own hidden option ids strands a watch. OpenCart deletes and re-inserts every option row on every product save, so the ids survive only because its own form posts them back. An importer or a bulk-edit tool that omits them, and changes the underlying option value, leaves a watch pointing at nothing. Such a watch is deleted rather than left waiting for an alert that can never come.

Delivery

  • A restock of three units does not mail the whole waiting list on day one. Each batch is sized from what is on hand (one alert per unit by default), oldest first, with an hour between batches. Both numbers are yours to change, and setting Alerts per unit in stock to 0 mails everybody at once.
  • Beyond the first batch, nothing sends unless something calls in. Saving a product in the admin, or an order change that puts stock back (a cancelled order, say), sends the first batch for those products in the same request. Every batch after that, and every restock made any other way, such as an import or a direct database edit, waits for the sweep. The sweep has to be woken: by OpenCart's own scheduler, by anything that can fetch a web address on a schedule, or from the command line. Any one of the three is enough, and a store with none of them sends that first batch and nothing more.
  • On OpenCart's own scheduler the shortest cycle is hourly. Setting Minutes between batches below 60 does nothing on such a store, because the sweep itself cannot run more often than that. Drive the sweep from the web address or the command line and the smaller number starts to mean something.
  • On OpenCart 4.1.0.4 the store's scheduler is broken inside OpenCart itself, for every extension on the store rather than this one. Nothing sends on that release until you point something at the sweep web address or run the command. Back In Stock says so on its own settings screen, with the address already filled in. The same goes for the daily sign-up digest: it rides the sweep, so on 4.1.0.4 it arrives only when something calls the web address or runs the command.
  • Rotating the sweep secret stops a crontab line that was working, at once, until the new address is pasted in. That is what rotating is for.
  • Somebody watching several variants of one product may get several mails at once. Three watches are three watches; each is answered on its own.
  • Our wording carries no images at all, including the store's logo. What arrives is the wording, the product name, the variant, a link to the product and a link to unsubscribe. The HTML part is yours to rewrite and is sent as you wrote it, so an image you add yourself goes out with it.
  • The mails carry no List-Unsubscribe header. OpenCart's mail library cannot send one: it accepts a subject, a sender and two body parts and nothing else. The one-click link inside the message is not affected. A store large enough to meet Gmail's bulk-sender threshold is already relaying through a mail provider, which adds the header itself.
  • Every word Back In Stock says to a shopper is yours, and nothing else is. Both emails, the consent notice and the heading above the capture form are written in the Wording section of the settings screen, per language, and an update does not reach what you wrote. Nothing else on that screen or that form can be reworded: the rest either names what a control does or restates a rule, and a consent notice that stops being true of what the extension does is a record that says the wrong thing. There is no rich-text editor; the HTML part of each email is written as HTML.
  • Both emails can be previewed, and test-sent to your own admin address, and a test counts toward nothing. Preview and test in the Wording section renders the confirmation or the alert, in any of your store's languages, from the saved wording around a sample product, so save first. Send me a test mails it to the address on the admin account you are signed in with and nowhere else: there is no box to type another address into, and an account with no address, or a store with no mail engine, sends nothing and says why. A test writes no sign-up, no consent record and no memory of a send, never reads the suppression list, and takes no share of the per-pass cap or of a batch. Its links open the page that says the link has been used or has expired. How.
  • Nobody is ever mailed an alert without confirming their address first. A sign-up sends a confirmation email carrying no price, no product image and no offer; the alert starts when the link in it is clicked. There is no setting that turns this off, which means a share of the people who fill the form in will never receive an alert. Unconfirmed sign-ups are deleted after seven days.
  • The one exception is a signed-in customer using their own account address, which the store has already proved through its own account flow. A signed-in customer typing a different address is treated as a guest.
  • Changing a retention period reaches only the people who sign up afterwards. The period is a sentence inside the notice each person read, and it is recorded against their sign-up. Everybody already waiting keeps the period they were promised.
  • Retention periods apply to the whole installation, not per store. A merchant trading in two jurisdictions gets the stricter period everywhere rather than one each.
  • Requests keep expiring while the extension is switched off. A promised retention period is not extended by the merchant's inattention. Switching the module off stops capture and stops sending; it does not pause the clock.
  • A suppressed address is suppressed on every store the installation serves. Somebody clicking stop all alerts has no idea the operator runs a second shop, and the two mistakes are not equally bad.
  • Only the merchant can lift a suppression. The page a customer reaches says so and tells them to ask. Lifting is recorded against the account that did it, permanently.
  • A lift signs nobody up and sends nothing. It only allows the address to ask again, from the product page, through the same confirmation email as anybody else.
  • Whoever can honour an erasure request can also lift a suppression. Both live on Catalog → Back In Stock and share its permission; they are not separately controlled.
  • Somebody signing up again while suppressed is told the same sentence as everybody else and receives nothing. Saying more would tell a stranger whether an address is on the list, which is the same thing said to somebody who is not. The one exception is a signed-in customer using their own account address, who is told they asked for alerts to stop.
  • An erasure request keeps a live suppression entry and deletes a lifted one. The live entry is the only thing preventing the emails from starting again, so deleting it would undo the request it was meant to honour. A lifted one suppresses nothing and is pure history.
  • Deleting a customer account does not delete their watches. A watch is keyed to an email address, and the person still holds the mailbox. Use Catalog → Back In Stock, look the address up, and erase it.

Abuse

  • There is no rate limiting, flood protection or abuse prevention of any kind, and none is planned. OpenCart tells an extension nothing about a visitor that the visitor cannot change: the address a request appears to come from is assembled from headers a caller supplies, with no list of trusted proxies anywhere in the store. A control built on that would refuse honest shoppers behind one office connection and stop nobody.
  • What a script can therefore cost you is one confirmation email per address it invents, a message carrying no offer and no price. Those rows delete themselves after seven days, and a Pending confirmation count climbing on Catalog → Back In Stock is what it looks like while it is happening.
  • The daily sign-up digest counts confirmed watches only, so a script inventing addresses moves nothing in it: a pending sign-up has confirmed nothing. A signed-in customer's own account address confirms at once, and counts. There is no email to you per sign-up, and there will not be one: with no throttle on the form, a mail per sign-up would hand any script a way to flood your own inbox. The digest goes to your store's own address, at most once a day, carries counts and product names and no address or customer name, and is off until you switch it on.
  • The controls that do exist are the store's own captcha, a hidden field a person never fills in, a 15-minute wait before one address can be sent a second confirmation email, and whatever sits in front of the store. None of them depends on anything the caller chooses. The hidden field and the wait answer with the same neutral sentence as a sign-up that worked. Switching the captcha on needs a captcha extension enabled under System → Settings → Option → Captcha; with none enabled the setting has no effect and the settings screen says so.
  • A store serving product pages from a full-page cache should leave the captcha off, and has the larger problem already: a cached product page offers or withholds the capture form according to the stock level at the moment it was cached.

Admin and reporting

  • There is no all-time demand figure and there cannot be. Requests are deleted on the schedule the shopper was promised, and the consent record that outlives them deliberately holds no product. Waiting now is live; Alerted is a rolling 60-day window. The two are never added together.
  • No admin screen exports subscriber addresses, and there is no list of suppressed addresses to browse. The address lookup answers a subject-access question for an address you already know, which is the question a customer asks. The API is the deliberate exception, and it is the reason that switch is off until you turn it on: a credential you create yourself can read the whole waiting list, addresses included, because a system that keeps your records cannot reconcile against a list it can only query one address at a time. It still cannot browse suppressed addresses, and it still cannot write anything.
  • The demand report downloads as a CSV, with counts only. Download CSV is the report as the screen shows it, under the same filters and sort and across every page, one line per counter: product id, model, product, variant, waiting now, longest wait in days, alerted in the window, and the alert state. No column holds an address, a language or anything a shopper typed; every cell is a count or a name your own staff typed into the catalogue. The line under the header says alerted is a window and not a lifetime total, and no cell is guarded against being read as a spreadsheet formula, because none carries shopper text to hold one.
  • A theme that rewrote the product form loses the admin tab, not the page. Where the anchors Back In Stock looks for are not there, it leaves the screen exactly as OpenCart rendered it.
  • A theme whose product page has no </form> after the Add to Cart button gets no capture form. The page renders as the theme wrote it; nothing breaks, and nothing is offered.

Removal

  • Uninstalling leaves all six tables in place, frozen. Nothing writes to them, the storefront no longer reaches them, and they do not grow, so reinstalling picks up exactly the state the uninstall left. The tables are back_in_stock_subscription, back_in_stock_setting, back_in_stock_consent_text, back_in_stock_consent_proof, back_in_stock_suppression and back_in_stock_memory, each behind your store's own table prefix. Uninstalling never empties them; a store owner who wants the tables themselves gone drops them with their own database tool.
  • Removing what is held about people is a screen of its own, and it cannot be undone. Remove everything held about a person, reached from Show me what is held, and how to remove it on the settings screen, lists every holding with a real count beside it before you confirm. It deletes every watch and every consent record, for everybody. It keeps the suppression list, because deleting it would let the mail start again, and it keeps your settings, your per-product switches and the consent wording versions, none of which is about anybody. It carries a permission of its own, extension/back_in_stock/customer/purge, so it can be withheld from somebody who answers individual requests.
  • Permissions granted at install are never revoked. A grant reaches only the group that installed the extension, where you may since have given the same screens to three more, so revoking would strip one and leave three. What is left behind is a permission row naming a route that no longer resolves, which does nothing at all.
  • A cron entry deleted in Extensions → Cron Jobs comes back on the next install. Switching it off is the supported way to stop the scheduled sweep, and that survives an update.

Coexistence

  • Where Preorder offers a pre-order for a counter, no capture form is shown there: the shopper can buy the thing now, so asking to be told about it later is the wrong offer. Deference follows Preorder's own rules and is per option value, so a size excluded from the pre-order still takes stock alerts.
  • A watch taken before a product became pre-orderable still mails. Only the form is withheld; nobody already waiting is dropped.
  • Somebody holding an unpaid pre-order line and a watch for the same variant may receive both mails. The two extensions do not read each other's rows.
  • Back In Stock requires no other extension, and specifically not Wishlist. It works the same on a store that never installs either.

Language

Back In Stock says more to a shopper than to you. The capture form on the product page, the confirmation email, the alert email and the consent notice underneath the form are all its own words, and every one of them is read by somebody who is not logged into your admin. Which of our strings a named native speaker has read, and in which language, is answered on the shared language promise page rather than claimed here.

Three points, the first of them the most important:

  • A string nobody has translated yet reaches a shopper in English, never blank and never as the identifier it is stored under. Every string of ours is served with English underneath it, string by string rather than language by language, so a half-finished translation is a page in two languages instead of a page with holes in it. That is a deliberate floor: a capture form printing button_notify where a button belongs is worse for a store than one that briefly says Notify me.
  • The screens you work in are translated as far as somebody has read them and no further, and the rest is English. A string a named reviewer has signed off is served in your admin language; 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, counted rather than claimed.
  • The heading above the capture form, the consent notice and both emails are yours to write, per language, and nothing else a shopper reads is. Each language is saved on its own, a box left empty uses our wording, and an update leaves what you wrote alone (see Delivery). Rewriting the consent notice mints a new version of the promise: everybody already waiting keeps the wording they read, and the next person is recorded against yours, so it has to stay true of what the extension does.

Anything not described on this page should be assumed absent. If you are about to rely on behaviour that is not written here, ask before you buy.