Skip to content

Changelog

What changed in each release of Back In Stock, in terms of what it means for you rather than which files moved.

1.5.1 — 3 October 2026

Fixes only. No setting was added or changed, nothing in the database changed, and the API answers with the same fields as before.

  • Alerts the mail server refused were counted as sent. OpenCart's mail engine reports a refusal by returning quietly rather than raising an error, so a store whose mail setup was broken marked every waiting person as alerted and mailed none of them. A refusal now counts as a failure: the person stays on the waiting list, and after three failed attempts the request is parked, as any other failure is. Send now tells you how many could not be sent, and the extension's log names the reason.
  • Send me a test and Rotate did nothing. Both buttons sent their request without your admin session, so it arrived at the login page. The test was not sent and the sweep secret was not changed. Both work now. The same fault sent the Wording section's language picker to the login page, and that is fixed too.
  • Send any alerts that are due now opened a page of raw code. The sweep did run, but the result was shown as bare data in place of the settings screen. The result now appears at the top of the settings screen. Send now on the product tab now says so when the store does not answer, rather than saying nothing.
  • Wording containing & or " gained a layer of encoding on every save. Tom & Jerry was stored as Tom & Jerry, and the next save made that Tom & Jerry. What you type is now stored as you typed it. If a box in the Wording section shows & or " where you typed & or ", correct it once and save. The update cannot tell your text from the stray encoding, so it does not change the boxes for you.
  • Product and store names are escaped where shoppers see them: in the heading above the capture form, in the consent notice, and in the message that thanks a shopper for signing up. A name containing < or & now reads as written. It can no longer change the page around it.
  • A shopper is told when the sign-up did not go through. If the store fails to answer the form, a sentence under the email field now says the address was not taken. Before, nothing happened.
  • The erase and remove buttons say when they get no answer. On Customers → Personal Data and on the settings screen's button that removes what this extension holds, a request that fails now says so. Before, the screen showed the same thing whether or not the removal had run.
  • The API refuses an API user whose key is empty. OpenCart's own form will not save one, but a row edited by hand could, and such a row let in a caller who presented no key at all. The API's published limits also gain one: a watch that its shopper signs up for again during a walk of the list can be missing from that walk. Before you delete a local copy that a walk did not return, fetch it by id. See the API reference.

1.5.0 — 28 September 2026

Three additions. Nothing you had set changes: the one new setting starts off, and what your store sends to shoppers after the update is what it sent before.

  • Preview either email, and send yourself a test. The Wording section of the settings screen now ends with Preview and test: pick the confirmation or the alert and a language, and Preview opens the email in a new tab as the sweep would build it from your saved wording, around a sample product. Send me a test mails the same email to the address on your own admin account, and nowhere else, with [Test] before the subject. A test counts toward nothing: no sign-up, no consent record, no alert, and no share of the per-pass cap or of a batch. How to use it.
  • Download the demand report as a CSV. Download CSV in the report's filter bar gives you the report as you are looking at it, with your filters and sort, across every page, one line per variant: product id, model, product, variant, waiting now, longest wait in days, alerted in the window, and the alert state. Counts and catalogue names only: no address and nothing a shopper typed. The line under the header says that alerted counts the last 60 days (or however long you keep alerted requests), so the file cannot be read as an all-time total.
  • A daily digest of new sign-ups, to your own address. A new switch under Alerts, Daily sign-up digest, off by default. When on, your store's own email address gets at most one email a day counting the watches confirmed since the last one, with the five most-wanted products. Counts only, no address and no name. Only confirmed watches count, so a script filling the form with invented addresses moves nothing. It goes out with the scheduled sweep (OpenCart's scheduler, the sweep web address or the command line) and never on a product save or on Send now. The first one arrives a day after you switch it on, and a day with nothing new sends nothing. What it counts.

The data/ directories still ship. 1.4.0 said they would come out once their migration had had a version to run in. This is the first release uploaded to the marketplace since 1.1.0, so most stores update to it straight from 1.1.0 and need those files read once more on the way. They come out in a later release.

1.4.0 — 21 September 2026

Your email wording and your consent notice are now settings, and an update stops overwriting them. This is a change in behaviour rather than a new feature. Read it even if you never edited anything.

Up to 1.3.0 the two emails and the consent notice were seven files under extension/back_in_stock/data/, and the guide told you to edit them there. An update in OpenCart deletes an extension's whole directory before the new one goes on, so every update silently took your sentences with it. Your customers went back to reading ours, no changelog warned you, and no log explained it afterwards. This release fixes that.

Updating to this release reads those files one last time and puts what it finds in the boxes. They are in a Wording section on the settings screen now (the subject, plain-text and HTML parts of both emails, the consent notice, and the heading above the capture form), one language at a time, each language saved on its own. A file you had edited becomes the box's contents. A file you never touched is left alone, so you go on getting our wording and every later improvement to it. Running the update a second time does not undo anything you have since typed on the screen.

Check the boxes after you update. The migration reads the files as they are on your store at the moment you take the extension off, which is the last moment they exist. It catches an edit that is there and cannot catch one you had already lost to an earlier update. If you kept a copy of something that never made it across, paste it in.

The data/ directories still ship, and nothing reads them any more. They come out of the package in a later release, once this migration has had a version to run in. Editing a file there now changes nothing at all.

Rewriting the consent notice mints a new consent version, exactly as editing the file used to. Everybody already waiting keeps a pointer to the exact wording they read, so nothing already agreed to changes underneath anybody. But what you write is what the next person is recorded as having agreed to, so it has to stay true of what the extension does.

Nothing else about your storefront changed. A store that never edited a wording file sends byte-identical emails and shows a byte-identical consent notice to the ones 1.3.0 sent and showed.

Everything Back In Stock puts in your database about a person is now published field by field, with what removes each one: table, column, why it is there, how long it is kept, and what an erasure does to it. It is at what this holds about a person, generated from the extension's own declaration rather than written beside it, so it cannot describe a column the code does not have or miss one it does. If you read nothing else on it, read two parts. The first is the consent record: the wording each person read, where the proof of it is kept, and the one-click withdrawal path, which is the same one click that gave it. The second is the two things kept for ever on purpose, each with the reason stated. The suppression list is one of them: it is the record that somebody asked not to be mailed, and deleting it on a schedule would start the mail again.

A new screen answers what do you hold about me for one named person. At Customers → Personal Data, you enter an email address and get back every holding: from this extension, from any other Kyvero extension you have installed, and from OpenCart itself. Each extension answers for itself and nothing there decides anything on another's behalf. It also prints what OpenCart's own account-deletion flow does and does not do on the release you are running. Read it before you promise anybody anything. There is a Remove it button on the same screen, which takes what each declaration says an erasure takes and keeps what it says is kept, with the reason shown against every line it kept. Here that means the watches and the consent proofs for that address go, and a live suppression entry stays, because deleting it is the single act that would let the mail come back to somebody who asked for it to stop. An entry you had already lifted is history and goes with the rest. Opening the screen needs OpenCart's own Modify on customer/customer: reading out everything a store holds about one named person is at least as privileged as editing their account.

And, on the settings screen, a button that removes everything this extension holds about a person, for everybody rather than one person. It is deliberately separate from uninstalling. Uninstalling deletes nothing at all, on purpose: an OpenCart update is an uninstall followed by an install, so an extension that dropped its tables on the way out would destroy your waiting list on a routine upgrade. So removing what is held is a thing you do on a screen, while you can still see what you are about to lose. It prints the plan first (every table with a real count beside it), reports what went rather than saying success, and cannot be undone. What goes is every watch and every consent proof. What stays is the suppression list, for the reason above, and your settings, your per-product switches and the consent wording versions, none of which is about anybody.

The new screens come with two permissions, and clicking + gives them to your own group. Customers → Personal Data is access on extension/back_in_stock/customer/personal_data with OpenCart's own Modify on customer/customer behind the act itself; the remove-everything screen carries access and modify of its own on extension/back_in_stock/customer/purge, so you can hand somebody the per-person screen without handing them the one that empties the lot. For any other group, tick them at System → Users → User Groups, and log out and back in.

1.3.0 — 11 September 2026

Reading your waiting list out through the API is much faster on a busy store, and updating puts the index there. The list is read a page at a time in a fixed order, and until now nothing in the database was arranged to serve that order, so each page was a read of the whole table. On a store with 200,000 rows that was 71.8 milliseconds a page; it is now 0.16, and walking the lot end to end went from about four and a half minutes to under a second. You do not have to do anything: updating adds the index to the table you already have. Nothing about what the API returns changed, so an integration built against 1.1.0 keeps working untouched.

The heading above the capture form is now yours to write. A new Wording panel on the settings screen holds one box: the line a shopper reads above the sign-up field on an out-of-stock product page. Pick a language, write it, save. Each language is saved on its own, so writing one leaves the others exactly as they were. Leave a box empty and Back In Stock's own heading is used, shown in the box in grey so you can tell inherited from written. Clearing a box puts our heading back rather than leaving the form without one, and an update does not reach what you wrote, unlike an edit to our files under extension/.

It is deliberately the only sentence on that form you can reword. Everything else there either names what a control does or restates the promise the consent notice is hashed from, and neither is safe to reword without changing what the page is saying.

Nothing else about your storefront changed. The consent notice, both emails and the waiting list read exactly as they did in 1.2.0. Under the surface the notice now resolves the same way the emails always have, so a store served one of our languages reads the notice and the mail from the same place rather than from two. This has no effect today, because English is still the only language shipped.

The Add a language guide has been rewritten. It used to tell you to copy our data/mail/en-gb/ directory and translate it; it now says what happens when you add a language to your store, and why we do not support copying that directory.

1.2.0 — 10 September 2026

On a store with one language nothing you can see changed. Back In Stock still ships English and only English, so every screen, every email and every consent notice reads exactly as it did in 1.1.0.

What it gains is the machinery for reading a translation once one exists: the extension now works out which of the languages it ships your store should be served, rather than assuming your store's language code is spelled the way our directories are. With one language shipped that question has one answer, so nothing about a single-language store changes today.

On a store with more than one language, the settings screen now tells you what that came to. A new Language section lists every language your store has, including any that are switched off, and says for each one which of Back In Stock's own translations it is served from and why: an exact match, a match on the language where we do not ship that region, or not translated, in which case anything Back In Stock has to say in that language is said in English. It is read-only, there is nothing to set, and it shows the answer this extension was already reaching on every page load. Nothing is reported to you anywhere else: the fact is shown on the screen it is about, not on your dashboard.

One thing was wrong and is fixed: the consent notice previewed on the settings screen now reads the language your storefront is set to. It used to read a setting that means something different in the admin. No merchant could see the difference while English was the only wording there was, but it would have shown you different words from the ones your shoppers agree to the moment a second language shipped. The preview and the storefront now read one file, so the wording on record is the wording somebody read.

1.1.0 — 7 September 2026

Nothing in the storefront changed. The capture form, the confirmation and alert emails, the sweep, the waiting list, the demand report and the erasure screen all behave exactly as they did in 1.0.0. This release adds one thing beside them and changes nothing that was already there.

Back In Stock now answers a JSON API, for a system that keeps your own records (an ERP, a warehouse system, a merchandising tool) rather than for a browser. It can read who is waiting: one watch at a time, or the whole list walked page by page, filtered by product, by variant, by store, by state or by when the person signed up. Each watch comes back with the exact consent wording that person read.

It is off until you switch it on, and while it is off every route answers as though the extension had no API at all. The switch is in a new API section on the settings screen, beside the base address, the versions being answered, a link to System → Users → API and a warning if there is no credential that could call it yet.

That switch is deliberately independent of the extension's own status. You can switch Back In Stock off in the storefront (no capture form, nothing sent) and the API keeps answering. Who is waiting is your own record, and a storefront switch should not hide it from the system that holds your data.

Before you hand the address to anybody:

  • The API only ever reads. Nothing can sign a person up through it, and nothing can unsubscribe them. Signing up is the shopper's act and so is stopping; a merchant honouring a request by hand does it on the waiting-list screen, which is where the record of who did it is kept.
  • The credential is OpenCart's own API user, and it is not scoped to this extension. 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.
  • Erasing somebody here deletes their rows outright. There is no "erased" marker to read back, because a watch is not an accounting record and nothing needs to outlive it. A watch that has gone from the API is a person who withdrew, was erased, or whose watch expired, and the three are deliberately indistinguishable. If you have synchronised watches into your own system, reconcile against the full list rather than waiting for a deletion notice that is never coming.

The API's own page is the API, and it is generated from what the extension answers rather than written beside it.

Everything each version promises stays answerable for at least twenty-four months after a replacement ships (see the API promise).

1.0.0 — 28 August 2026

The first public release. There is no previous version, so nothing below is a change; this entry is the baseline every later one is measured against.

What ships: a notify me when it's back field on your out-of-stock product pages, bound to OpenCart's own size and colour picker and needing no account; confirmed opt-in, with no setting that turns it off; a versioned record of the exact wording each person agreed to; one-click unsubscribe with stop every alert and delete everything you hold about me on the page it lands on; alerts sent only when a customer could buy the thing, oldest waiting first and staggered against the stock on hand; the waiting list and the address lookup at Catalog → Back In Stock; the per-variant demand report with wait times; a Back In Stock tab on the product form; and three ways to wake the sweep: OpenCart's own scheduler, a web address, or the command line. What it does not do is the shorter list; read it first.

It runs on OpenCart 4.0.2.0, 4.1.0.3 and 4.1.0.4, and refuses to install below 4.0.2.0 rather than half-working. On 4.1.0.4, use the web address or the command line: that release cannot run any scheduled task at all, for any extension on the store. See requirements and install.

What an update keeps

Two things are true of every update:

  • Nothing on the waiting list is lost, and neither are the consent records, the suppression list or the sweep secret. No table is dropped by anything this extension does.
  • The wording you wrote comes back, in every language you wrote it in: both emails, the consent notice and the capture heading. It is a setting rather than a file, which is what makes that true. Up to 1.3.0 it was files and an update did overwrite them (see the entry above).

Your settings come back, with the exceptions below. An update is an uninstall and then an install, and OpenCart deletes an extension's settings at the uninstall step. Back In Stock keeps its own copy of them and puts them back afterwards. They are one set for the whole installation rather than one per store.

These are asked for again rather than put back:

  • module_back_in_stock_status — Whether the module is on is OpenCart's to set, and an extension putting it back for itself is an extension deciding it should be switched on. Switch it back on after an update with the Status switch on this extension's own settings screen, which Extensions > Modules opens with its Edit button: the module list itself has no switch.
  • module_back_in_stock_captcha — An update putting this back to off breaks no promise made to anybody: it leaves a door unlocked, where every other key here would hold personal data longer than a live notice said or stop a mail somebody was waiting for. Set it again if you had it on.
  • module_back_in_stock_diary_verbose_until — Detailed logging comes back off after an update, the way a fresh install does. An upgrade is an uninstall and a reinstall, and putting a diagnostic window back is how a store ends up verbose months after the support exchange that asked for it ended.

A setting a release adds does not change what your store does. Its default is what Back In Stock did before the setting existed, so an update never asks you to go and set something to get back the behaviour you already had.

What this cannot tell you is whether a release changed how a setting behaves, as against whether it survives. Nothing derives that from the code, so it is written by hand: a release that changes an answer you relied on says so in its own entry above, as its own paragraph and never among what is new.