Settings¶
Back In Stock keeps its settings in OpenCart's own setting table, under the
module_back_in_stock group. You set them at
Admin > Extensions > Extensions > Modules > Back In Stock.
Each key below carries where it applies. per store means a multi-store install can hold a different answer per storefront, and both are honoured: a read takes what that store holds, then what the default store holds, then the shipped default. install-wide means one thing serves every storefront, and the key's own description names that one thing.
Scope¶
| Key | Default | What it does |
|---|---|---|
module_back_in_stock_statusinstall-wide |
0 |
Whether the extension is enabled. Set by the Status switch on this extension's own settings screen, and off is off everywhere: no capture form is offered and nothing is sent. Nothing is consumed while it is off either — the send test is a level rather than an edge, so switching it back on mails everybody still waiting and still sendable. Off costs latency, never an alert. The one thing it does not stop is expiry: a row dies on the schedule it was promised whether or not the merchant was paying attention. |
module_back_in_stock_api_enabledinstall-wide |
0 |
Whether the extension answers API requests at all. Off, every API route answers 404 api_disabled in the API's own JSON envelope, so an extension with its API off is shaped like one that has none. Read once for the whole installation from the default store rather than per store, because the credential it checks is OpenCart's own API user, which has no store of its own. It is a separate switch from the extension's own Status: an installation may want the waiting list running and no API, and — because the two are read independently — the API answers whether or not Status is on, which is deliberate. A merchant's own records are not something a storefront switch should hide. |
Alerts¶
| Key | Default | What it does |
|---|---|---|
module_back_in_stock_min_quantityinstall-wide |
1 |
How many units have to be on hand before a counter counts as back in stock. Applied to both quantity columns, which is why it is install-wide: OpenCart keeps one stock figure for every store, so a per-store gate would make the same option value available and unavailable at once. |
module_back_in_stock_alerts_per_unitinstall-wide |
1 |
How many people each unit in stock is worth mailing, so three units landing does not mail fifty people a link to a page that sells out. Decimals are allowed. Zero means mail everyone at once. On by default, which makes this extension the category outlier deliberately: the off position mails forty-seven people a link to an out-of-stock page, and it is the merchant who receives those complaints. |
module_back_in_stock_batch_minutesinstall-wide |
60 |
How long one batch holds the next one off, in minutes. Its own setting rather than the sweep cadence, so a store sweeping every ten minutes still staggers hourly if that is what it wants. Install-wide because the batch is counted per counter, and a counter is one oc_product quantity column shared by every storefront. |
module_back_in_stock_max_per_passinstall-wide |
200 |
The most alerts one pass may send, which bounds what a single call can do. Zero is uncapped. Whatever is left over keeps its state and goes on the next pass. Install-wide because it bounds one wake-up of one scheduler, and an installation has one. |
module_back_in_stock_digestinstall-wide |
0 |
Whether the store's own address gets one email a day counting the watches confirmed since the last one, with the five most-wanted products. Counts only: no address, no name. Only confirmed watches count, so a script filling the form with invented addresses moves nothing. It rides the scheduled sweep and never a product save. Off by default, because it is mail to the merchant, and a merchant who never asked for it would read it as noise. |
Retention¶
| Key | Default | What it does |
|---|---|---|
module_back_in_stock_expire_unconfirmed_daysinstall-wide |
7 |
How many days a sign-up nobody confirmed is kept before it is deleted. No consent record is written for it, because a watch that never reached confirmed has no consent to prove. |
module_back_in_stock_expire_confirmed_monthsinstall-wide |
12 |
How many months a confirmed watch that never fired is kept, from 1 to 24. This number is inside the consent notice the shopper reads, so changing it mints a new wording version and reaches only the people who sign up afterwards: everybody already waiting keeps the period they were promised. |
module_back_in_stock_sent_daysinstall-wide |
60 |
How many days an alerted row is kept, so the unsubscribe link in the mail goes on working. It is also the window the demand report's Alerted column counts over, because a figure covering a longer period than the rows survive would be a number the table cannot answer for. Sixty is CASL's endpoint number and the shortest period that keeps an unsubscribe honest; a merchant whose own regime is longer sets it longer here rather than being told what their jurisdiction says. |
module_back_in_stock_proof_yearsinstall-wide |
3 |
How many years a consent proof is kept after the watch it records ended. The proof is what answers "who agreed to what, and when" after the watch itself is gone, so it outlives every other row here. Three years is the German limitation bound; a store under a regime that asks for longer sets it longer. This number is printed in the consent notice the shopper reads, so changing it mints a new wording version and reaches only the people who sign up afterwards. |
Capture form¶
| Key | Default | What it does |
|---|---|---|
module_back_in_stock_captchainstall-wide |
0 |
Whether the capture form carries whichever captcha extension the store has enabled under Settings > Option > Captcha. Off by default, and the usual argument on this screen does not transfer: confirmed opt-in and batching default on because their off position makes the merchant a spammer, where a default-off captcha makes nobody a spammer and a default-on one taxes the conversion rate of every store on the one surface whose whole proposition is no account, no login, one field. Nothing breaks when no captcha extension is enabled; the form simply carries none. |
module_back_in_stock_copyinstall-wide |
empty | Everything this extension says to a shopper that a merchant may say differently, in their own words, per language code: the heading above the capture form, the consent notice beside it, and the subject, plain-text and HTML parts of both emails. Read whole to render one page and written whole by one form POST, so it is one setting key holding an array rather than a table. Empty for a language means the wording this extension ships, which is what the box shows in grey. Seven of the eight used to be files under data/ that every update deleted; they are here because a merchant's own words cannot survive in a file the package ships, and the update that first read them out of those files is the release that declared this. Nothing else on the capture form may be reworded: the rest either names what a control does or restates a rule, and a notice that stops being true of what the extension does is a consent record that says the wrong thing. |
Merchandising¶
watching — install-wide
Whether the capture form is offered for one counter — a product, or one option value of one — set on that product's Back In Stock tab. The combining rule is preorder's and it is stated here rather than assumed: an option-value row overrides the product row, and no row at all means the counter inherits. Absence is what "not overridden" is stored as, so a product nobody has touched has no rows, and an option value that must say "not offered even though the product is" gets a row of its own saying so rather than the column becoming a tri-state. Install-wide because one oc_product quantity column is shared between storefronts, which is the same reason the rationing is.
status— Whether the form is offered for this counter. A row saying0suppresses it where the level above offers it. Starts at1.
Reports¶
| Key | Default | What it does |
|---|---|---|
report_back_in_stock_statusinstall-wide |
1 |
Whether the demand report is offered under Reports. Stored under the report extension's own setting code rather than the module's, because that is the code core reads the Reports list from and deletes with the report row. |
report_back_in_stock_sort_orderinstall-wide |
0 |
Where the demand report sits in the Reports list, read by core exactly as it is for every report extension. |
Advanced¶
| Key | Default | What it does |
|---|---|---|
module_back_in_stock_stale_cyclesinstall-wide |
3 |
How many sweep cycles may pass with nothing swept before the settings screen says so. One missed hour is a blip; three is a pattern. It covers five failures nothing can tell apart — a dead scheduler, a crontab line never added, a host that disabled cron, a request answering 500, and a merchant who switched the job off. |
module_back_in_stock_sweep_secretinstall-wide |
empty | The shared secret a sweep called over HTTP is compared against, generated at install. Rotating it is its only control: there is no free-text edit, because a secret a merchant can type is a secret a merchant can shorten. An empty one refuses every call rather than admitting every call. It is remembered across an update on Rotate's own argument — rotating stops a crontab line that was working until it is re-pasted, which is why that button confirms and says so, and a control that needs a confirm dialog is a control an update must not operate. |
module_back_in_stock_diary_verbose_untilinstall-wide |
0 |
When detailed logging stops, as a unix timestamp, and 0 is off. Turning Detailed logging on from this extension's settings form stores the moment two days from now; the writer compares that against the clock every time it is asked for a DEBUG line, so the window closes on its own with no scheduled task and nothing to clean up. While it is open this extension records what it did in far more detail, and the shared diary consequently holds less history. |
What you cannot change, and why¶
These are fixed on purpose. Each one is a decision with a reason beside it rather than a setting nobody got round to adding.
Scope¶
Every setting here is install-wide and there is no store selector, which is this extension alone among the ones sold here. The reason is OpenCart's own stock column: it keeps one oc_product.quantity for every store, so units shared between two storefronts have to be rationed between them too, and the minimum-quantity gate appears in the predicate at both levels — a per-store gate would mean the same option value was available and unavailable at once on a pair of stores sharing the column. The expiry periods were the only genuine candidates and are declined on their own ground: the schedule shipped here is already the strictest of the regimes, so a per-store expiry is not a merchant serving a second jurisdiction, it is a merchant loosening a promise on a settings screen. The variation that genuinely exists is handled already and without a setting — the consent notice is content-addressed, so a second store's name and address hash differently by construction.
Capture form¶
Confirmed opt-in is not optional and there is no setting for it. Every address proves itself by clicking a link in a mail sent to it, and a store that would rather mail unproved addresses is a store asking for a setting whose only effect is to make its own sending reputation somebody else's problem. The one exception — a signed-in customer asking to watch with the address already on their account — is not a second lifecycle either: confirmed_at is simply already set at insert, and one branch in the whole extension decides whether to stamp it and skip the mail.
There is no throttle on the capture form, and there will not be one. Every key one could be built on is either supplied by the caller — OpenCart overwrites REMOTE_ADDR from a header on both releases and has no trusted-proxy list, and a script that ignores Set-Cookie gets a fresh session every request — or shared with real shoppers, where capping it hands any script a kill switch over a real store's form. What is between the form and the database instead is the captcha, the honeypot, the per-address cooldown and confirmed opt-in, none of which a caller can choose its own value for.
How long one confirmation mail holds the next one off is a constant and not a setting. The hour-long cooldowns elsewhere in OpenCart govern failed authentication or re-notification, where this one governs a person asking again for a mail that has not arrived — and an hour of silence loses them.
| Rule | Value |
|---|---|
| One confirmation mail holds the next off, in minutes | 15 |
Where the capture form and the product tab are spliced into a page is fixed, and the markup they look for is not configurable. A template this extension cannot place them in keeps core's own page untouched rather than losing it — so a theme that rewrote the product form loses the form, and the store keeps the page.
| Rule | Value |
|---|---|
| The capture form goes after this, searched from the add-to-cart button | </form> |
| The add-to-cart button both releases identify this way | id="button-cart" |
| The admin tab link goes in the list holding | href="#tab-general" |
| The admin tab pane goes in the container holding | id="tab-general" |
A test goes to the address on your own admin account and nowhere else. A box you could type any address into is a way to send this store's mail to anybody, from a screen anyone with modify on this extension can reach.
Alerts¶
The batch is per counter and deliberately not per store, because OpenCart keeps one quantity column for every store: units shared between two storefronts have to be rationed between them too. Two overlapping passes may between them mail a slightly larger batch, and that is accepted rather than locked against — the cost is a handful of extra invitations, and the alternative is a lock around the one mechanism every wake-up shares, which trades a bounded over-invite for an unbounded stall.
Batching ships on, which makes this extension the category outlier deliberately. Both products that ship staggering have it off by default and one puts it behind a paid tier. A default-off position mails forty-seven people a link to an out-of-stock page, and it is the merchant who receives those complaints. It also costs nothing in the common case: a rate of one binds only when watchers outnumber units.
There is no email to the merchant for each sign-up. The capture form has no throttle and cannot have one (see capture_throttle), so a mail per sign-up would hand any script a way to flood the store's own inbox. A daily count of confirmed watches gives the same news, and a script cannot move it.
Merchandising¶
Send now is disabled, with its reason printed, wherever the level test would refuse — there is no setting that makes it mail anyway. Over-inviting is the merchant's call and lying is not a setting, so a Send now that cheerfully accepts a click and mails nobody is the same lie one layer down.
There are no addresses on the product tab and no remove-a-subscriber, and neither is a setting. A product form is opened to change a price, and a hundred addresses next to a select-all is one copy-paste from a mailing the consent wording never covered — while the permission that opens that screen is modify catalog/product, which every merchandiser has. Who is waiting links to Catalog > Back In Stock, which carries its own permission and its own masking.
Reports¶
A report extension's own screen carries two things and may never carry a third: whether it is listed, and where. A merchant looking for a setting looks at the module's screen, and a report's edit screen is reached by a path nobody walks twice — so a knob hidden down it is a knob that does not exist.
Advanced¶
How many failed sends park a watch is fixed. A breaker threshold is not a merchant judgement — a parked row is never destroyed by the failure and a merchant may retry it by hand, so what the number decides is how long a dead mailbox is retried before somebody is asked to look at it, and there is no answer a store could give that would be better than this one. review_requests makes the same call about its own.
| Rule | Value |
|---|---|
| Failed sends before a watch is parked | 3 |
How long a claim may be held before a later pass takes it back is fixed. It is a property of how long one pass can credibly be mid-flight rather than anything about a store's catalogue, and a value set too low mails the same person twice.
| Rule | Value |
|---|---|
| A held claim is reclaimed after, in minutes | 15 |
How much randomness is behind the sweep secret and a subscription's token is fixed. A shortenable secret is the thing the rotate-only control exists to prevent, and a length a merchant can choose is a length a merchant can choose badly.
| Rule | Value |
|---|---|
| Bytes behind the sweep secret | 32 |
| Bytes behind a subscription's token | 16 |