Discount Rescue
Privacy Policy
Discount Rescue holds no personal data about your shoppers. It watches one thing in your checkout — the moment a discount code is refused — and stores what happened: the checkout’s own identifier, the text that was typed into the discount field — truncated, because that field also accepts gift cards — the cart subtotal at that moment, and the rescue code it issued. No name, no email address, no phone number, no postal address, and no card data. Shopify redacts card field values before the app can see them, and the app keeps only the first four characters of anything longer than eight typed into the discount field.
1. Who we are
Discount Rescue (listed on the Shopify App Store as “Orumio — Discount Rescue”) (the “app”) is built and operated by Orumio (“we”, “us”).
| Operator | Orumio |
|---|---|
| Representative | Masanori Iwata |
| Address | Mitsuhashi Building 3F, 1-3-3 Kita-Aoyama, Minato-ku, Tokyo 107-0061, Japan |
| Contact | support@orumio.com |
| Telephone | We will disclose this without delay in writing or by email upon request. Please send requests to the contact address above. |
When you install the app on your Shopify store, you are the controller of the data in your Shopify store, and we act as your processor: we process it only to provide the app to you, on your instructions. The terms of that relationship are set out in our Data Processing Agreement, which forms part of your agreement with us.
2. What the app processes
2.1 What the checkout pixel sends
Installing the app activates a Shopify web pixel in your checkout. It runs in Shopify’s strict sandbox and forwards exactly four kinds of event to us: the checkout starting (identifier and cart subtotal), the shopper typing into the discount field, the error Shopify then displays under that field, and the checkout completing. Every other checkout event is dropped inside the sandbox and never leaves the shopper’s browser.
The error we key on is the structured alert Shopify itself renders — its type, the field it belongs to, the value that caused it and its message. We decide whether to rescue from the field, never from the words in the message. The pixel declares no consent purpose at all — analytics, marketing and preferences are all off and sale of data is disabled — which is what allows it to run as strictly necessary rather than as tracking.
The pixel keeps one value in the sandbox’s own session storage: the current checkout’s identifier, so that an error arriving without one can still be matched to the right checkout. It is cleared when the browser session ends. The app sets no cookie in a shopper’s browser and nothing that survives the session.
2.2 What the checkout block sends
The offer block you place in the checkout editor reports its own state back to us: that it has mounted on a given checkout, whether that checkout will accept a discount code at all, whether a discount is already on it, and the timings of the offer being shown, accepted and applied. Every report, and every read of a rescue, carries the checkout session token Shopify issues to the block — signed with the app’s own secret and naming your store — and the app refuses a request without one. That report is what makes a rescue possible: a code is issued only for a checkout the block itself has reported live from inside your checkout.
2.3 Orders, where Shopify has granted access
To tell you which orders carried a rescue code, the app subscribes to new orders in your store. It reads the order’s identifier and name, its total, the discount codes on it, and its checkout identifier. It stores that row only when one of the discount codes is a rescue code we issued to you; an order that carries none of ours is counted and forgotten.
This is protected customer data under Shopify’s rules, and the app is gated on Shopify’s grant per store. Until your store is granted it, the app answers Shopify’s order notifications without reading them, stores nothing about any order, and the dashboard says “pending order access” rather than showing a zero.
2.4 Deliberately not requested
The app requests Level 1 protected customer data and no Level 2 field. It does not declare, ask for, read or store a customer’s name, email address, phone number or address, and it never queries customers. It has no use for them: a rescue is decided from a cart subtotal and a failed code, and attributed by the code itself.
2.5 Stored by the app
| Data | Personal data? | Why it exists |
|---|---|---|
| Your shop’s myshopify domain | No — a business identifier | Identifies your installation |
| Shopify access and refresh tokens | No — credentials | Lets the app issue and delete rescue discounts, and read the plan of your store, while nobody is signed in |
| Checkout identifier (checkout token) | No — an opaque Shopify identifier for one checkout | Ties an error, the block’s report, a rescue code and an order together. Truncated in logs |
| The text typed into the discount field, truncated | No, unless a shopper types something personal into a discount field — and never a whole gift card number: anything longer than eight characters is kept as its first four characters and its length | Classifying what failed — an expired code, a code that does not apply to this cart, or no such code — happens on the full text in memory; what is stored is evidence for why a rescue was or was not offered |
| The error Shopify displayed: its type, field, value and message | No — Shopify’s own message about the checkout | The failure itself. Eligibility keys on the field; the message is kept as evidence only |
| Cart subtotal and currency at the moment of the error | No | The minimum cart subtotal and the cap you set are checked against it |
| The rescue code, its type and value, and the times it was issued, shown, accepted and applied | No | The rescue itself, and the join to the order it reached |
| Order identifier and name, total, and the amount the rescue code was worth | No — order-level fields, no customer field | Telling you which orders carried a rescue code. Stored only where Shopify has granted protected customer data access to your store |
| Daily counters | No — aggregate only, with no identifier of any kind in them | The Results page. They are written as events happen so that the rows above can be deleted on schedule without losing the totals |
| Your settings and your plan | No | Whether rescue is on, the amount, the minimum cart subtotal, the cap, and whether the store is on Plus |
3. Why we process it
One purpose only: to provide the app — detecting a refused discount code in your checkout, deciding against the limits you set whether to offer an alternative, issuing and withdrawing that code, and reporting to you what happened. That is the purpose we declared to Shopify when we requested access to order data, and the app reads no order for any other reason.
We do not, and the app has no mechanism to:
- use your data for marketing or advertising, or profile anyone for those purposes;
- sell or share your data with anyone;
- use your data to train machine-learning models;
- build analytics or audience products out of your data, or out of your shoppers’ behaviour.
- use anything a shopper types into the discount field for any purpose but the decision described above.
The app makes no automated decisions about people. Its decision is about a checkout, not a shopper: a fixed set of rules you configured, applied to a cart subtotal and to which kind of code failed. There is no scoring, no profiling and no model. Two shoppers who type the same code into the same cart get the same answer.
4. Who else processes it (sub-processors)
The app talks to a deliberately small number of external services. While it is processing your data, the server communicates with one destination — the Shopify Admin API — and the public pages on this domain are fetched from Orumio’s own hub site, which receives no store data. There is no analytics SDK and no error-reporting service receiving payloads.
| Service | Role | Data it can see |
|---|---|---|
| Shopify | The platform your store and its checkout run on | All store data — Shopify is the source of truth, and its own privacy terms govern it |
| Vercel Inc. | Application hosting, the scheduled cleanup job and runtime logs | Data in transit while a request is served, plus the runtime logs described under logging |
| Neon Inc. | Database (Postgres), encrypted at rest with automated backups | Everything the app stores, as listed above, at rest |
Our database and application servers are located in the United States. If you are in the European Economic Area or the United Kingdom, this means your data is transferred outside that region; the safeguards for that transfer are set out in the Data Processing Agreement.
5. How it is protected
- Minimisation first. No shopper name, email address, phone number, postal address or card data is read or stored at any point. Card field values are redacted by Shopify before the alert reaches the pixel, and the discount-field text — which can be a gift card number — is truncated before it is written. Data that was never stored cannot be leaked from storage, exposed in a backup, or taken in a database breach.
- A code cannot be minted from outside your checkout. The offer block’s reports and reads are authenticated with the checkout session token Shopify signs for it, and a rescue is issued only for a checkout the block has reported live. Three counters bound the rest: at most sixty rescues per store per minute, at most five hundred per store per day — past which the app switches rescue off by itself and tells you on its status page — and at most five discount-code errors per checkout.
- Encryption in transit. The app is served only over HTTPS, and the database connection requires TLS.
- Encryption at rest. Our database provider encrypts all data and backups at rest. There is no self-managed backup, export or snapshot pipeline, so no unencrypted copy of the database exists anywhere. The access token the app uses to reach your store is encrypted a second time, by the app itself, before it is written: it is stored only as AES-256-GCM ciphertext, tied to your store’s domain, under a key held outside the database. Someone holding a copy of the database cannot use it to reach your store.
- Tenant isolation. Every record reaches your installation by foreign key, and every query filters through it.
- Endpoint authorisation. Your admin screens require an authenticated Shopify admin session; the scheduled job requires a bearer secret and refuses to run when it is not configured; every webhook route rejects an invalid signature before the payload is parsed.
- Log hygiene. Logs record identifiers, classifications, counts and timestamps. Fields whose names indicate a credential are replaced with a marker before a line is written, and checkout identifiers are truncated, so a log line on its own cannot be replayed against the app.
- Access control. The app is operated by a single person. There are no staff accounts, contractors or support agents with access to merchant data. Every account with access is protected by two-factor authentication and a unique password generated and stored in a password manager.
We maintain a written data protection policy and a security incident response policy, and we review both whenever what the app does with data changes.
6. Logging
The app writes operational logs so that failures can be diagnosed. Those lines record identifiers, classifications, counts and timestamps — never access tokens, never webhook signatures, and never shopper personal data, because none is held. Checkout identifiers are truncated to their first characters.
Logs are held in our hosting provider’s runtime log storage. No log data is forwarded to any external log or analytics service.
7. Cookies and tracking
The app sets no advertising, analytics or tracking cookies, and no cookie of any kind in a shopper’s browser. Inside the Shopify admin it authenticates with Shopify session tokens rather than its own login. Shopify may set its own cookies as part of the admin, the storefront and the installation flow; those are governed by Shopify’s privacy terms, not this policy.
The one thing the app keeps in a shopper’s browser is the current checkout’s identifier, held in the sandbox’s session storage and gone when the session ends. It identifies a checkout, not a person, and it is not read on any other site, on any later visit, or by anything but this app’s own pixel.
There is no tracking of shoppers across sites, no device fingerprinting and no advertising identifier anywhere in the app.
8. How long it is kept
- Rescue codes are removed from your admin. A rescue code expires thirty minutes after it is issued, and the scheduled job deletes the discount behind it from your Shopify admin. One exception, by necessity: a code the shopper has already applied stays while it sits on their checkout — deleting it would take the discount off their order — and is deleted as soon as that rescue settles, at the order or at the twenty-four hour mark. Deleting the code does not change an order that already used it.
- Checkout-level rows are deleted after 90 days. The error, the block’s report and the checkout context — the checkout identifier, the text typed into the discount field, the subtotal — exist for debugging and for the counters, and go at ninety days.
- Rescues and rescued orders are deleted after 13 months. Attribution reporting is the reason they are kept, and thirteen months is the longest window the dashboard offers.
- The daily counters are kept for the life of the installation. They are aggregate only — no checkout identifier, no code, no order identifier — and they are written as events happen, so the deletions above lose nothing you can see.
- When you uninstall, the app deletes its stored credentials at once and stops processing.
- Deletion. Shopify sends us a shop redaction request approximately 48 hours after uninstall; that deletes your installation record and everything attached to it — settings, checkouts, errors, rescues, orders and counters.
- Backstop. Because that request is a webhook and can fail to arrive, the app itself deletes any installation that has been uninstalled for more than 30 days, with the same cascade. The window is long enough never to pre-empt a reinstall, and finite so that a lost message cannot become indefinite retention.
9. Requests from shoppers
If a shopper asks to access or delete their personal data, that request belongs to the merchant whose store holds it. Shopify forwards such requests to us as well, and we handle them as follows:
- Data request: we return nothing, because we hold no shopper personal data.
- Customer redaction: no action is required for the same reason. The app stores no customer identifier of any kind — there is nothing in our database that a customer id could match.
- Shop redaction: we delete the merchant’s entire tenant as described under how long data is kept.
If you are a shopper and are not sure which merchant holds your data, write to support@orumio.com and we will help you reach them.
10. Security incidents
If we confirm an incident affecting your data, we notify the affected merchants directly and in plain language — what happened, what data was involved, what we have done, and what if anything you need to do — targeting within 72 hours of confirming it. We also report incidents involving protected customer data or platform credentials to Shopify promptly, without waiting for a complete root-cause analysis.
11. Changes to this policy
If we change what the app does with data, we update this page and its version number before the change ships. Material changes are announced to merchants with an active installation.
12. Contact
Questions, requests, or anything that looks wrong in this policy: support@orumio.com.
Discount Rescue · Version 1.0, 6 September 2026 · Data Processing Agreement
Discount Rescue is an independent product of Orumio and is not affiliated with, endorsed by, or sponsored by Shopify Inc. Shopify is a trademark of its owner.