Reliable COD is a Shopify app that helps merchants reduce cash-on-delivery losses. It scores a buyer's order history within a single store and uses that score to hide Cash on Delivery at checkout, tag risky customers, and flag risky orders before the merchant ships them.
This policy explains what the app receives, what it stores, what it never stores, who else sees it, and how long any of it lasts.
For buyer data, the Shopify merchant who installs Reliable COD is the data controller and Reliable COD acts as their processor: we only process what the merchant's own store already holds, and only to provide the app's function to that merchant. For merchant account data — the store domain, the installing staff user's name and email, the merchant's own configuration — we are the controller.
We do not sell data. We do not share data between merchants. We do not use anyone's data to train models.
Reliable COD requests these Shopify access scopes: read_orders, write_orders,
read_customers, write_customers, read_products,
write_payment_customizations.
Order data reaches the app two ways, both running through the same pipeline:
orders/create, orders/cancelled,
orders/fulfilled and refunds/create, from the moment the app is installed.read_all_orders permission, so
60 days is the app's entire historical reach, by design.From each order the app reads the buyer's Shopify customer ID, the email and phone on the order and on its billing and shipping addresses, the order ID and date, whether the order was cancelled, whether it was fulfilled, and whether a refund restocked the goods. It also reads the shipping address country, used only to interpret the phone number's format.
The app's checkout logic runs inside a Shopify Function. Shopify Functions cannot make network calls and have no storage of their own: what the function reads at checkout — the cart, the delivery address, the total, and the customer's tags — is never transmitted anywhere and never retained. Its only other input is a configuration setting the merchant themselves wrote.
The app does not store buyers' phone numbers or email addresses. To recognise a returning buyer it stores a salted, per-store cryptographic hash (HMAC-SHA256) of each, alongside Shopify's own numeric identifiers and dated true/false facts about what happened to each order. The hashing key is derived per store, so the same phone number produces a different value in every store and two merchants' records can never be joined.
We treat those hashes as personal data, and we want to be plain about why. A phone number is at most about ten digits and an email address is drawn from a small, enumerable population. A salted hash over an input space that small is not anonymisation — it is pseudonymisation: anyone holding the salt and a list of candidates could confirm a match by brute force. So these hashes are erased on an erasure request exactly as raw identifiers would be. We do not treat an erasure request as a no-op on the grounds that "it's only a hash".
| Record | Contents | Personal data? |
|---|---|---|
| Order facts | Store domain, Shopify order ID, Shopify customer ID, phone hash, email hash, order date, and three outcome flags (cancelled / fulfilled / refund-restocked) | Yes — pseudonymised, as above |
| Session | Shopify access token and the installing staff user's name and email, stored by Shopify's own session library | Merchant staff data |
| Store, rules, plan, order counts | Store domain, install dates, the merchant's rule configuration, plan state, per-day order totals | Merchant data |
| Operational log | Events, counts and reasons used to diagnose failures | No — see below |
The operational log holds no identifiers by construction. Error text is passed through a redaction step that removes email addresses and long runs of digits or hexadecimal before anything is written. Where an identifier cannot be processed, the log records which kind of identifier failed and how many — never the value, and never a hash of it.
These live in the merchant's own Shopify data, where the merchant can see and change them:
rc-risk:med and rc-risk:high, plus rc-blocked if the merchant sets itRTO-RISK and an order note explaining why an order was flagged| Service | Role | What reaches it |
|---|---|---|
| Supabase (PostgreSQL) | Database hosting | The stored records in section 3 |
| Vercel | Application hosting | Application traffic, and logs that have already been redacted |
| Resend | Email delivery | One alert per flagged order: the merchant's own email address, the order number, and the reason sentence. No buyer identifiers. |
There is nothing else. No analytics provider, no advertising, no third-party data enrichment, no cross-merchant aggregation.
Reliable COD scores the last 90 days of order outcomes. Anything older than that has no effect on any decision the app makes.
A buyer asks their merchant, and Shopify forwards the request to us. We record it and the merchant responds directly within 30 days. For a buyer we hold records on, the disclosable material is: the salted hashes on their order-fact records, the Shopify order IDs and dates, the three outcome flags, and the risk level derived from them — plus the tags written onto their Shopify customer record, which the merchant can already see.
On a buyer erasure request we delete every order-fact record for that store matching the buyer's Shopify customer ID, the hash of their phone number, the hash of their email address, or any specific order named in the request. Where an identifier is shared — a phone number used by more than one person, for example — we delete more rather than less. The cost of that is lost accuracy for the merchant; the cost of the alternative would be an erasure request left unfulfilled.
48 hours after a merchant uninstalls, Shopify sends a store erasure request and we delete every record belonging to that store across all of our tables. We keep one audit entry recording the store domain, the time, and how many rows were deleted per table. It contains no customer data, and we keep it because being able to show that an erasure ran is part of complying with it.
Material changes will be reflected here with a new effective date and version number above. The app's behaviour and this document are kept in step deliberately — if they ever disagree, the app's behaviour is the fact and this document is the error, and we will correct it.
Questions about this policy, or a request relating to your data: hello@kalythegrowthstudio.com.
Merchants: you can also raise anything through the app's listing on the Shopify App Store.