Back to MarginShield

Privacy Policy

Last updated: September 21, 2026

MarginShield is operated by A2E Group Pty Ltd, trading as MarginShield (“MarginShield”, “we”, “us”). This policy explains how we collect, use, store and disclose personal information when you use the MarginShield true-margin platform. It is written to align with the Australian Privacy Principles (APPs) and, where applicable, the EU General Data Protection Regulation (GDPR).

1. Information we collect

We collect the following categories of data:

  • Account data: name, work email, role, organisation name, and the authentication credentials you create.
  • Business data: product catalog, cost structure (landed cost, fulfilment cost, payment-processing rate, margin floor), supplier agreements and rebate rules, attachment definitions, approval decisions, and audit events generated by your use of the platform.
  • Competitor observations: public-web prices and product information you have instructed MarginShield to monitor, plus any voice price-discovery transcripts you initiate.
  • Shopify install data (BAFO for Shopify): when BAFO for Shopify is installed on a store, or opened from a Shopify admin, Shopify tells us about the store and about the staff member doing it. What we keep, where, why, for how long and how to have it deleted is set out in Section 2, under “The merchant's own data”.
  • Website enquiries: when you use our contact form, your name, email address, company, the number of sites and the plan you ask about, your message, a hash of your IP address and your browser's user-agent string. We use them to reply to you, and the IP hash and user-agent string only to spot abuse of the form; we clear those two 30 days after the enquiry. The enquiry itself is kept as correspondence until you ask us to delete it or we delete your account.
  • Free store audit: when you run our free audit without an account, the store address you give, any product pages, competitor domains, country and postcode you add, any email address you choose to leave, your IP address and the result of the scan. We use your IP address only to stop repeated or abusive scans: we clear it 24 hours after the audit, and a count of your recent scans is kept in our cache for about an hour. If you create an account from the audit's link within 30 days, the audit becomes part of your account's data; otherwise we delete it 30 days after it ran, when its link has expired.
  • Usage data: authentication logs, application events, performance telemetry, and error reports used to operate and improve the service.

We do not knowingly collect sensitive personal information (health, biometric, political, religious, or trade-union data) and you agree not to upload it.

2. BAFO for Shopify: data we process and why

BAFO for Shopify is the optional “Seen it cheaper?” and “Want our best offer?” feature a merchant can add to the product and cart pages of their Shopify storefront. It processes a narrower, separate set of data about that merchant's own shoppers and orders, in addition to the business data described in Section 1, and it records who installed it. This section sets out exactly what it collects, why, who processes it and when it is deleted.

BAFO for Shopify uses the store’s saved settings: shoppers may submit requests, automatic offers run only where enabled for the store, and merchant fees apply only when disclosed and enabled.

The review-only service is the default. A merchant can later authorise a separate, measured offer experiment for a particular store and for either test or live orders. No measured experiment collects anything until an active certificate records the current owner or admin's agreement to this September 21, 2026 disclosure, the store's current installation, a granted and verified read_orders scope, verified order webhooks and retention job, and an exact active experiment. Live collection also requires Shopify's protected customer data approval. Reinstalling the app, withdrawing that authority, removing the scope, disabling the consenting person, stopping the experiment or switching off collection closes the gate. Nothing collected as test data is later relabelled as live data.

When that experiment is active, BAFO records an eligible exposure and a stable treatment or control assignment on its server before the storefront can show an invitation. The record contains the experiment and policy versions, the surface, currency, item and variant counts, when it became eligible and when its outcome window matures, plus keyed hashes of the cart and, for a logged-in shopper, the Shopify customer ID. It never contains the raw cart token or customer ID. Control assignments, shoppers who ignore an invitation and eligible shoppers who do not buy remain in the denominator; later invitation, selection, issue, application, checkout, payment, cancellation, refund, complaint and repeat-order events are recorded when they occur.

Roles. For BAFO for Shopify, the merchant who installs the app is the data controller of their shoppers' data. MarginShield is the data processor, acting only on the merchant's instructions to run the feature they configured. Full processor terms are in our Data Processing Agreement. BAFO stores nothing a shopper submits from a store until an owner or admin of the store's BAFO workspace has agreed there to our Terms of Service and Data Processing Agreement for that store; until then every request from that store gets a neutral “unavailable” answer. For the data BAFO records about the merchant's own staff when they install or open it (“The merchant's own data”, below), MarginShield is the controller.

When a shopper asks for an offer. BAFO receives an offer request only when a shopper opens the BAFO prompt, answers its questions and submits it. For each request, BAFO stores:

  • The shopper's reason and answers. The reason they chose (a lower price elsewhere, a loyalty benefit, a better basket, or delivery, installation, pickup or the cart total) and their answers. For a lower price, that is the competitor and price they gave, and their confirmation that it is for the same product and quantity and available now. For a loyalty benefit, it is the benefit they selected and whether they are logged in. For a better basket, it is the option they selected and, if the merchant suggests an add-on product, that product's variant ID. When the merchant has enabled bounded response ranking, the shopper can also add an optional clarification of at most 280 characters. It is shopper-authored text; the form asks the shopper not to include personal or payment details. Because it is free text, it may still contain personal information or a price the shopper chooses to enter.
  • What the shopper was looking at. The currency; whether the shopper is logged in (yes or no only); the product on the page, with its product and variant ID, product and variant title, price and availability; the add-on product the merchant has chosen to suggest, if any, with the same details; and the cart's total, item count, and each line's product ID, variant ID, quantity and price. BAFO no longer collects the country the storefront is set to for the shopper (Shopify's localisation country): the storefront does not send it, and BAFO discards it before storing a request if a storefront still running an older version of BAFO sends it. Requests stored by earlier versions of BAFO can still hold it until they are deleted under the periods below.
  • A hashed Shopify customer ID, only when the shopper is logged in to the store. Shopify adds a logged-in shopper's customer ID to every storefront request it passes to BAFO. BAFO stores only a one-way keyed hash (HMAC) of it with the request, never the ID itself. In request-collection mode it is used to find the shopper's requests when Shopify asks for their data to be provided or deleted (described below). Where BAFO's automatic offers are enabled for the store, it is also used to check eligibility for loyalty benefits, to stop one shopper holding overlapping offers for the same cart and to tie an issued offer to that shopper. BAFO also checks the ID against the request's own answer to whether the shopper is logged in. In request-collection mode, the request's stored fingerprint is keyed without the customer ID. Where automatic offers are enabled, the ID also contributes to that fingerprint to recognise repeat requests. The hash is never shown on the merchant's Requests desk or included in a customer data request's download. A request from a shopper who is not logged in holds no customer hash. Requests made with automatic offers enabled, and some earlier requests, can hold a fingerprint keyed with the ID until they are deleted under the periods below. Our hosting providers' own request logs can hold the ID (see “No IP address” below).
  • Keyed hashes of the cart token. The storefront sends the shopper's cart token with each request. BAFO stores two one-way keyed hashes of it: one of the full token, which ties the request to that cart and enforces the request limit, and one of the token with its secret “?key=” part removed, which is the only way an order can be linked to the request (see Orders below). It also stores a keyed hash of the whole request, used to recognise a request that is sent twice. The raw cart token is never stored.
  • The outcome. The response shown to the shopper, which the merchant's hold or decline replaces once they review the request, and BAFO's internal decision record: how the request was decided, any hesitation score (described below) and, once the request is reviewed, the decision, who made it, when, and any internal note the reviewer added (never shown on the storefront, but included when the shopper asks for their data, as described below). If an offer is issued, the one-use offer entitlement: its terms and expiry, the discount code that applies it, and the same hashes.
  • No IP address. BAFO does not read, hash or store the shopper's IP address. Our API's request logs record only each request's method and path, never its query string or body. Our hosting providers, Vercel and Railway, keep their own logs of the requests they carry for us, which can include the IP address a request came from (for a storefront request, possibly the shopper's) and its full address, including the customer ID Shopify adds for a logged-in shopper. Vercel keeps these logs for at most 30 days and Railway for at most 90 days, depending on our plan with each, and they are used only to operate and troubleshoot the service.

Before a shopper asks, a product page can check whether BAFO is available for the product shown. That check sends only the product and variant IDs, the currency and the quantity, plus the details Shopify adds to every storefront request, and BAFO stores nothing from it (the hosting-provider request logs described above cover it as they do every request).

What the merchant's review team sees. The Requests desk in the merchant's BAFO workspace shows each request with its reason, the competitor and price the shopper gave (for a lower price), the product on the page, its status, when it was made and any hesitation score, the cart it was made from (its item count, its total and, for each line, the product ID, variant ID, quantity and price) and, once it has been reviewed, any internal note the reviewer added. No product name is stored for a cart line, so none is shown. The desk never shows the hashed identifiers described above.

Cart-behaviour signals. On cart pages where the merchant has switched on “Prompt a hesitant cart shopper” (it is off when the BAFO block is added, until the merchant switches it on), and only while Shopify's Customer Privacy API reports that the shopper has allowed analytics, the storefront counts how the shopper uses the cart: how long the cart page has been open and visible, how long since the shopper last interacted with it, how many times a quantity was changed, how many times checkout was selected, whether the pointer left the top of the page (exit intent), and how many times the BAFO pop-up was closed. Each count is capped. The counts are saved in the browser's session storage, which the browser clears when the tab is closed. They are not reused once 30 minutes have passed since they were last saved, and they are deleted as soon as the page finds that analytics consent has been withdrawn. Without analytics consent, nothing is counted, saved or sent. These signals are used for two purposes:

  • The automatic invitation. When the counts show signs of hesitation and the cart page has been open and visible for at least the merchant's chosen delay (15 to 120 seconds; 45 seconds by default), the BAFO pop-up can open by itself to invite the shopper to ask for an offer. It opens only if Shopify's Customer Privacy API also reports, at that moment, that the shopper has allowed marketing. Without marketing consent it never opens by itself. Opening the pop-up sends nothing; a request is made only if the shopper submits one.
  • Merchant review. If the shopper submits a request while analytics consent is in place, the counts are sent with it and stored with the request. BAFO calculates a 0–100 hesitation score from them, which the merchant's review team sees next to the request.

The signals and the score are never used to set, change or influence a price, or to decide whether an offer is made. A shopper who opens BAFO themselves, using the “Seen it cheaper?” or “Want our best offer?” button, can always submit a request, whatever their consent choices.

Orders. In the default review-only mode, the app subscribes to four Shopify order notifications. Shopify sends the order created, order paid and order cancelled notifications only for orders it marks as test orders, so BAFO is never notified that a real order was placed, paid or cancelled. Shopify sends the refund created notification for every refund in the store, because a refund carries no test-order flag of its own that Shopify's filter could use (only each of its payment transactions says whether it was a test, and a refund with no transaction would then never be sent). Shopify trims each notification before sending it: an order notification carries only the order's ID, its test-order flag, its cart token and the time the order was last updated, and a refund notification carries only the ID of the refunded order and the refund's own ID. The last-updated time and the refund's ID are included only so that Shopify does not discard a later notification as a copy of an earlier one; BAFO does not use them. BAFO uses the cart token only to check the link described below, never stores it, and logs none of these fields. BAFO then looks up and stores an order only if all three of these are true:

  • Shopify marks it as a test order. BAFO never looks up or stores any other order. BAFO checks the test-order flag itself, and again in Shopify's answer when it looks the order up, rather than relying on Shopify's filter alone.
  • It is linked to a BAFO request made in the same store: it was checked out from the same cart the shopper sent that request from (matched by the keyed hash of the cart token with its secret key removed), or BAFO has already stored an event for that same order after linking it.
  • The store's currency, as Shopify reported it when BAFO was installed or last reconnected, is one BAFO reads order facts in: AUD, EUR, GBP, NZD or USD. BAFO checks this before making any call to Shopify. In a store whose currency Shopify shows with two or fewer decimal places, shoppers can still make requests and the merchant can still review them even when it is not one of those five, but BAFO never looks up or stores an order. In the few currencies Shopify shows with three decimal places, such as KWD, BAFO cannot record a request.

A refund is stored only if BAFO has already stored an event for the refunded order. For every other order or refund, BAFO acknowledges the notification, makes no call to Shopify and stores nothing from it. If an order it does not store is a test order, BAFO notes only why it was not stored (it had no cart token, no BAFO request was made from its cart, the link could not be checked, or the store's currency is not one BAFO reads order facts in) and when, so that the merchant can see on the BAFO Orders page why it is missing. Each note replaces the previous one, contains no order ID, cart token, customer detail or other part of the notification, and is deleted when the app is uninstalled. BAFO keeps nothing at all about an order that is not a test order.

For a linked order, BAFO reads the order from Shopify, not from the notification, and stores only the order's ID, name (such as #1001), test flag, currency, financial status and last-updated time; its total price and total refunded; and each refund's ID and total. It does not request or store the order's line items. With them it keeps the notification's type, its Shopify event ID, when it arrived and the cart-link hash, and a record that the order is a test order on which no BAFO fee was charged. BAFO never requests or stores the order's customer, email, phone number, address or note.

In an explicitly authorised measured experiment, the same four notifications are reconciled for the certificate's test or live environment. BAFO reads the current cumulative Shopify order after each delivery and stores its immutable environment, order and event IDs, revision time, financial and cancellation status, whether taxes are included and whether the order was edited; cash received, refunded and retained; current subtotal, discount, tax, shipping, duty, additional-fee, tip and total amounts; and refund totals. For each line it stores product and variant IDs, ordered, current and refunded quantities, original amount, Shopify's reported discount allocation, the current price after all discounts and before taxes, and original and refunded tax. For each refund it stores its time and total, refunded lines, quantities, subtotal and tax, restock state, and refunded shipping and shipping tax. It still never requests or stores the order's customer, name, email, phone number, address or note. Duplicate deliveries are recorded once; revisions only move forward, equal-time disagreements are quarantined, and refunds received before a paid notification are reconciled from the cumulative order rather than added twice.

The Performance page reports assigned treatment and control denominators, non-buyers, ignored invitations, paid, cancelled and refunded outcomes, missing links and provisional financial coverage. Retained payment comes from Shopify's net payment amount. Merchant-supplied landed product, payment, fulfilment, delivery, return, operating, support, inventory-recovery and BAFO-fee components remain unknown until an authoritative source supplies them. While any required component or conservation check is missing, contribution stays provisional and BAFO shows no uplift or commercial decision. Complete mature results are descriptive differences per assigned eligible shopper, before and after the BAFO fee; they are not presented as a causal claim.

Each exposure's primary analysis cutoff is fixed when the exposure is first recorded. Shopify's order-created time, rather than when a notification reaches BAFO, decides whether an order belongs to that primary window. A late notification, refund or cancellation for an order created inside the window updates that order. A newly created order outside the cutoff is labelled and retained only as a later relationship fact: it has no primary maturity date and cannot change the measured result. Each cost or fee revision is also bound to the exact cumulative order snapshot it describes. BAFO carries a value across an edit or refund only through an explicit matching revision that names the earlier snapshot; it never silently reuses an old cost.

Why BAFO keeps order facts. They let the merchant see, on the BAFO Orders page, each test order checked out from a cart that made a BAFO request, and whether it was paid, cancelled or refunded, with its total and the amount refunded. They are also how BAFO recognises a later refund or cancellation of the same order after the request itself has been deleted, and how it finds the offer requests made from a customer's order when Shopify asks for that customer's data to be provided or deleted. BAFO keeps them for 400 days after each notification arrived (see “How long we keep it” below): a year and a month, so that the merchant can reconcile a full year of BAFO test orders and their refunds. In a measured experiment they also provide the paid, refunded, cancelled, repeat-order and retained-contribution outcomes for the eligible treatment and control denominator, including eligible shoppers who never buy.

Who processes it. Only these sub-processors, each also listed in Section 7, receive BAFO for Shopify shopper or order data:

  • Vercel hosts app.bafo.io, the address Shopify sends every BAFO storefront request and every Shopify notification for BAFO to. Vercel passes each one on to our API.
  • Railway hosts our API, which processes every request and notification and runs the automatic deletion described below.
  • Neon is our Postgres database, in the Asia-Pacific (Singapore) region, where BAFO data is stored.
  • Anthropic receives the shopper's selected reason and, only when the shopper supplied one and the merchant enabled it, the bounded clarification, together with opaque one-request candidate identifiers, fixed response-template identifiers, action-type, explanation and capability-status codes, and ordinal ranking values. It selects among server-owned non-monetary response templates. The adapter supplies no structured shopper or customer ID, passive behaviour or hesitation score, product or cart ID, system price, merchant cost, margin floor, budget, monetary candidate or offer amount. The optional clarification is free text and may contain personal information or a price the shopper chose to enter. Anthropic never supplies shopper-facing prose.
  • Sentry receives error reports from our API when an error occurs, and, for a sample of the API's requests (10% in production), performance traces that record how long the request, and each step in handling it, took. Our web app, which hosts app.bafo.io, sends nothing to Sentry. Before either is sent, our API removes any request body, cookies, query string, IP address and User-Agent string, and every request header except Accept, Content-Type and Content-Length. It also drops every detail Sentry's software records about a traced request, or about a step in handling it, unless it is on a fixed list of safe technical facts, such as the request method, the response status, the route and sizes; a web address keeps its path but loses its query string, a database or cache step keeps only its first word (such as “select”), and nothing our code writes to its own log is sent. A detail that a future version of Sentry's software adds is therefore dropped too. Reports sent before this filtering was introduced, including performance traces that could carry a request's IP address and User-Agent string, are kept for the retention period set in our Sentry account.

No other sub-processor receives BAFO for Shopify shopper or order data: none of it is sent to Stripe, Resend or PostHog. Resend, our email provider, delivers the emails about a customer data request (described below) to the owners and admins of the merchant's MarginShield account, with a copy to MarginShield. They give the store, when the request arrived, its deadline and how many records BAFO holds, and never the customer, an order or anything from those records. BAFO for Shopify never sells shopper data, never shares it with any third party other than the sub-processors listed above, and never uses it to train external foundation models.

Optional learning. When the merchant explicitly enables local learning, BAFO uses that store's eligible experiment assignments, response choices and linked purchase, refund and complete contribution outcomes to evaluate fixed, non-monetary response templates. Shoppers who ignore an invitation or buy nothing remain in the comparison. This learner runs inside MarginShield; it sends no records to an external model provider. It cannot change the merchant's financial permissions. Disabling local learning restores the fixed baseline for future decisions.

Shared learning is off by default and requires separate, expiring owner consent. It combines only permitted, clipped aggregate counts and scores with policy and lineage hashes in MarginShield's database. It does not share customer, cart or order identifiers, raw costs or individual rewards, and the aggregate reader returns no merchant identity. Withdrawal, expiry or an installation-authority change removes the contributed aggregates through the bounded retention process; a deletion count and irreversible lineage receipt remain. A shared candidate still needs that store's own evaluation before activation.

Shopper-linked learning decisions and assignments follow their underlying exposure's retention and customer-deletion rules. Derived strategy and evaluation artifacts retain policy identifiers, hashes, aggregate scores, counts and audit results, without raw shopper or order payloads, until the associated installation or organisation is erased. Turning learning off stops future use; it does not erase the audit history.

How long we keep it. BAFO deletes this data automatically: a scheduled deletion job removes it once it reaches these limits:

  • Offer requests, and the offer entitlements issued from them: 90 days after the request was made. A request whose entitlement is still live is kept until that entitlement expires.
  • Bounded-ranking operational records (provider and model, configuration revision, opaque context and candidate-set hashes, status, token counts, estimated cost, latency, fixed failure code and timestamps): after the same configured period as offer requests. They contain no clarification, prompt, generated response, shopper identity, cart or product facts, price, cost, margin, budget or offer amount.
  • Customer eligibility records, if any exist (each holds a hashed customer ID and the loyalty benefits it qualifies for): when they expire, or once 90 days pass without the record being refreshed, whichever is sooner.
  • Order and refund events, and BAFO's records of uninstall and compliance notifications: 400 days after they arrived.
  • Measured order receipts, snapshots, line and refund components: once the order was last observed more than 400 days ago and its outcome window has matured. Eligible exposure and assignment records, including control assignments and non-buyers: once their outcome window matured more than 400 days ago and no measured order still depends on them.
  • Customer data requests (described below): 90 days after they reached BAFO, whether or not they were answered. This period is fixed.

These are BAFO's default periods. They can be changed only within fixed limits (31 to 365 days for offer requests and eligibility records, and 90 to 730 days for order and refund events), and automatic deletion cannot be switched off. A deleted record can remain in our database's encrypted backups until they roll off, as set out in Section 6.

The deletion job runs at the start of MarginShield's regular scheduled run, before and separately from the other work in that run, so a failure in that work cannot stop it and a failure in the deletion job cannot stop that work. It is also scheduled on its own, so it does not depend on that run being scheduled. Our API logs every run of the job with how many records of each kind it deleted and whether any step failed, and no identifiers.

Uninstalling, and Shopify's deletion requests.

  • Uninstalling. When Shopify tells BAFO the app has been uninstalled, BAFO immediately clears its copy of the store's Shopify access and refresh tokens, revokes every offer entitlement issued in the store and stops all collection: new storefront requests are declined without being stored, and order notifications are ignored. The uninstall itself deletes no shopper data.
  • Shop redact. Shopify sends this request 48 hours after the app is uninstalled. When it arrives, BAFO deletes that store's offer requests (with their entitlements), customer eligibility records, customer data requests, measured exposures and order outcomes, and every stored Shopify event, except its records of the uninstall and of the shop-redact request itself. Unless the store has been reinstalled since, BAFO also marks it uninstalled, and then holds no data about the store's shoppers or orders. If the store has been reinstalled since the uninstall, the reinstalled store stays connected, with its Shopify access, its order-link note and the records collected since the reinstall, and BAFO deletes only those records from before the reinstall. Nothing is collected between an uninstall and a reinstall, so that is all of the store's shopper data from before the uninstall. BAFO treats the store as reinstalled when it is connected again and was last installed after the uninstall Shopify notified or, if that notification never arrived, less than 48 hours before the request; a store connected for longer, whose uninstall was never notified, is treated as uninstalled, and its merchant reconnects it by opening BAFO again from the Shopify admin. If the shop-redact request never arrives, the periods above still apply.
  • Customer redact. BAFO deletes that customer's eligibility records, offer requests and open customer data requests, found by the keyed hash of their Shopify customer ID, which every request they made while logged in to the store carries. For each order Shopify lists in the request that BAFO stored, it also deletes every stored event for that order and the offer requests (with their entitlements) made from that order's cart, including requests made while the shopper was not logged in. In the default review-only mode, the following applies: BAFO stores only test orders linked to a request, never a real order, so a request made while the shopper was not logged in cannot be found through a real order: it is deleted when its period above ends. When a measured live experiment was explicitly authorised, BAFO also deletes the listed live order outcomes, their receipts, lines and refunds, and the eligible exposure linked to the customer hash or those orders.
  • Customer data request. BAFO holds no name, email, phone number or address for any shopper, but it can hold pseudonymous records about one. It counts the customer's stored records: offer requests found by the keyed hash of their Shopify customer ID (which every request they made while logged in carries) or made from the cart of an order Shopify lists in the request, the entitlements issued from those requests, the customer's eligibility records and the stored events of the listed orders. It deletes nothing. A measured experiment also adds the customer's matching eligible exposures and the listed orders' measured outcomes to those counts. As with a customer redact, a request made while the shopper was not logged in is found only through a listed order that BAFO stored. In default review-only mode that can only be a test order; an explicitly authorised live experiment can hold the listed live order. If it finds no records, the request is resolved at once, BAFO keeps nothing that identifies the customer, and no one is emailed. If it finds any, BAFO keeps the request open, holding nothing about the customer except the keyed hash of their Shopify ID and the IDs of the listed orders it holds events for; it never stores the customer's name, email, phone number, address or Shopify customer ID, or Shopify's ID for the request. It then emails up to 20 active owners and admins of the merchant's MarginShield account that a customer data request is waiting, with the store, when the request reached BAFO, the deadline (30 days after that), how many records of each kind it holds and a link to the BAFO workspace. The email names no customer or order. If no owner or admin can be emailed, BAFO reports the failure to Sentry, identified only by BAFO's own ID for the request, with the attempt and recipient counts, and tries again on its scheduled runs, up to six attempts in all. The workspace's Data requests page shows each request's date, deadline, record counts and whether the email was delivered, never the stored hash or order IDs. Only an owner or admin can download a waiting request's records, as a JSON file for the merchant to send to the customer: the customer's offer requests as stored (without the cart token), each with its stored response less any discount code, the offer entitlements issued from them (without their discount codes or signed tokens), their eligibility records and the listed orders' stored events. For measured experiments it also includes the matching exposure timeline and the listed orders' financial snapshots, lines and refunds, without keyed hashes or the merchant's cost, fee and support-source records. Each request comes with the two parts of the merchant's decision record that are about the shopper: its hesitation score and, once reviewed, the review's outcome, time and any internal note. The file leaves out every keyed hash, who reviewed the request and the rest of the merchant's decision record, and says so. After sending it, the owner or admin marks the request as sent, which is allowed only after a download, records who did it and when, and deletes that hash and those order IDs. BAFO never contacts the customer itself. Every request is deleted 90 days after it reached BAFO, whether or not it was answered, or sooner by a shop-redact request; a customer-redact request for the same customer deletes an open one. If an owner or admin cannot download the records, the merchant can ask privacy@marginshield.io for help reaching the download; we never send the records themselves by email.

BAFO's records of these uninstall and compliance notifications contain no customer or order details. Each one identifies only the store, or just the type of notification, and records a test-only flag and a zero fee amount. The record of a customer data request also holds the counts described above, and nothing that identifies the customer; the open request described above is kept separately. The record of a shop-redact request that finds the store reinstalled also holds the time of the reinstall, and nothing else.

The merchant's own data. When someone installs BAFO on a store, or opens it from the store's Shopify admin, BAFO learns from Shopify who they are, and uses that to create their MarginShield account or sign them in. MarginShield is the controller of this data.

  • About the store. Shopify tells us the store's myshopify address, name and currency and whether it is a development store, which we keep with the store's connection. Until an account is connected they are kept, with the store's Shopify access, as a pending install that expires 30 minutes after Shopify grants access and is deleted by the next run of the scheduled deletion job, or at once if the app is uninstalled first. We do not ask Shopify for the store's account email. The store's Shopify access tokens are stored encrypted. When the app is uninstalled, Shopify's notification carries the store's own details, which can include its owner's name, email and phone number and the store's address; BAFO reads only the store's ID from it and keeps none of the rest.
  • About the person. Shopify tells us the staff member's Shopify user ID, name, email and language, whether Shopify has verified that email, and whether they own the store or are a collaborator. BAFO does not use or keep the language. The per-user Shopify access token that carries these details is discarded as soon as they are read, and is never stored.
  • Verified email and Shopify identity. BAFO treats an email as an email credential only if Shopify has verified it. If Shopify has not verified the email on a store's first install, BAFO does not look up, compare or store that address. It creates the store's separate organisation and a Shopify-only owner account with an undeliverable sign-in address and no contact address, then binds that account to the store and Shopify user ID. Only that same Shopify user ID can later open that store's workspace through Shopify while the owner and organisation remain active. A different Shopify user ID cannot use a matching email to enter it. On a connected store that has no such identity binding, an unverified email is refused; the organisation's audit log records whether the person owns the store and the reason, and nothing that identifies them: no Shopify user ID, email or hash of one.
  • What we keep. For a store that is not yet connected, BAFO creates a MarginShield organisation named after the store and an owner account holding the name Shopify gives for the person (or the store's name, if Shopify gives none); it sends no email when it does. When Shopify has verified the person's email and no other MarginShield account uses it, the owner account also holds that email, with no usable password until they set one. If another MarginShield account already uses that verified email, the new account keeps the email only as its contact address and has no email sign-in and no password: its owner signs in by opening BAFO from their Shopify admin, and nothing is written to, or said about, the other account. If Shopify has not verified the email, the owner account instead has an undeliverable sign-in address, no contact address and no usable password, and BAFO keeps the binding between the store connection, that account and the numeric Shopify user ID. The organisation's audit log records their Shopify user ID, whether they own the store or are a collaborator, whether Shopify verified their email, and whether the account signs in through Shopify only. Each later sign-in from the Shopify admin is recorded in the audit log with the person's Shopify user ID and whether they own the store. When someone whose email does not belong to a member tries to open the store's workspace, the audit log records whether they own the store and the reason, and nothing that identifies them: no Shopify user ID, email or hash of one. BAFO connects a store to an existing MarginShield account only when that account already belongs to the person and nobody else can use its workspace: it must be the workspace's owner and only member, with no pending invitation or API key, and its own email address must have been verified with MarginShield. If BAFO created that account at an earlier install and nobody has set a password on it, opening BAFO from Shopify already signs its owner in, so the store joins that workspace directly; any other such account's owner signs in to it with its password and connects the store. Either way the audit log records that they did. Before BAFO stores anything a shopper submits from a store, an owner or admin of its workspace is asked there to agree to our Terms of Service and Data Processing Agreement for that store, having been shown this Privacy Policy; the store's record and the audit log keep who agreed, when, and to which versions of the three pages.
  • Why. We use these details only to create that person's MarginShield account or sign them in, to keep the audit log's security record of who installed BAFO and who signed in, and of refused attempts, to connect the store, and to limit how many stores one person can connect in a day: by default, one person can connect BAFO to at most three stores in any 24 hours. That limit is counted from the Shopify user ID and, only when Shopify verified it, the email already recorded above, so nothing new is stored for it. The counters that limit how often the install pages can be used are kept in our Redis cache for at most two minutes, keyed only by the store's myshopify address or the organisation, never by a person, email or IP address.
  • How long. The organisation, the account and the audit log are kept while the account is open. Uninstalling BAFO, and Shopify's shop-redact request, delete the store's credentials and shopper data as described above, not the MarginShield account, with one exception. An organisation that exists only because of the install (BAFO created it, nobody has set a password on it and it has no billing account) is deleted automatically 30 days after Shopify's shop-redact request for the last store connected to it, unless one of its stores is reinstalled first: everything it holds is deleted in the same way as when an account is deleted on request, described next, including its audit log's personal details. Otherwise there is no self-service account deletion: to have the account deleted, email privacy@marginshield.io. We then delete everything we hold for the organisation and its users, including BAFO's shopper and order data for its stores and its store connections, except its audit log, which is never deleted: the Shopify user IDs, emails, hashes of emails, names and phone numbers in it are replaced with “[redacted]”, and the organisation and user records it refers to are kept only as suspended placeholders, with the name, email and password removed (Section 6 lists the other records kept the same way). Deleting the account does not uninstall BAFO from the store (the merchant does that in Shopify), and installing BAFO again afterwards creates a new organisation. A deleted record can remain in our encrypted backups until they roll off, as set out in Section 6.
  • Who receives it. Vercel hosts the install pages and the BAFO workspace; Railway hosts the API that runs the install; Neon stores the records. Resend delivers any email we send the person, such as the customer data request notices described above. If our product analytics is switched on, PostHog records the person's page views (Section 10), each with the page's web address, which on the install pages includes the store's myshopify address; we never send PostHog their name or email, or any shopper or order data.

3. How we use it

  • Operate the MarginShield service, including the deterministic margin engine, Decision Desk, Scenarios Lab, rebate management, and the approvals queue.
  • Compute true-margin recommendations and surface competitor-pressure context at the point of decision.
  • Send the notifications, alerts and approval routing you configure.
  • Maintain an audit trail of margin-affecting decisions, and of who installed or signed in to BAFO for Shopify, for your own compliance and governance use. Nothing in it is ever deleted or changed, except that the personal details Section 6 lists are replaced when we delete your account.
  • Limit how many stores one person can connect to BAFO for Shopify in a day, to stop the free install being abused (Section 2).
  • Process billing through our payment processor (Stripe).
  • Communicate with you about your account and the service.

We do not use your data to train external foundation models. BAFO's optional local and shared policy learning is limited to the purposes and consent choices described in Section 2. We do not sell or share your data, your competitor observations, or your supplier-funding terms with any third party.

4. Tenant isolation

Tenant isolation is enforced by PostgreSQL row-level security, which is enabled and forced on every business-data table. Most carry an org_id column; the rest inherit tenancy through a parent record. Buying-group clean rooms compute aggregates server-side without materialising cross-member joins. Your catalog, costs, rebates, and decisions are visible only to your organisation and the users you grant access to.

5. Security

We implement encryption in transit (TLS 1.2+) and at rest (AES-256), role-based access control, append-only audit logging, Argon2id password hashing, and incident response. Full posture published at /security.

6. Data retention & deletion

We retain your data while your account is active. There is no self-service account deletion: to close your account and have its data deleted, email privacy@marginshield.io. You may ask us for a copy of your data within 30 days of closing your account; after that, we delete the account's data from our live systems within 90 days. Our background job queue holds a copy of some data only while a job waits or runs (such as an alert's recipient and text, or a catalogue file being imported) and deletes it automatically, within a day of the job completing, seven days of it failing, or seven days of being queued if it never runs; we also remove your organisation's jobs from it when we delete your account. Your account's audit trail is never deleted: when we delete an account, we replace the names, email addresses and hashes of them, phone numbers and Shopify user IDs in it with “[redacted]”, clear the IP addresses and browser details recorded with it, and keep the organisation and user records it refers to only as suspended placeholders, with the name, email address and password removed. Our own operator log entries about your account are kept with the same values replaced, as is, for a member of a buying group, its clean-room access log (query types and counts only). Encrypted backups roll off within a further 90 days. Some records (billing, audit events tied to legal obligations) may be retained longer where required by law. BAFO for Shopify shopper and order data follows its own retention periods and deletion triggers, set out in Section 2, and an account BAFO for Shopify created when it was installed, which nobody has set a password on, is deleted in the same way automatically once its stores have been uninstalled, as Section 2 describes.

7. Third-party sub-processors

MarginShield uses a limited set of sub-processors to deliver the service: Vercel (web hosting), Railway (application hosting, and the Redis cache and job queue), Neon (database, Asia-Pacific (Singapore) region), Cloudflare (R2 object storage, only when large-file catalogue import is switched on: the catalogue files you upload for import), Stripe (billing), Anthropic (bounded selection among fixed non-monetary BAFO response templates, using the shopper's selected reason and optional bounded clarification, never margin or offer calculation), OpenAI (text embeddings of product names, brands, categories and barcodes, to match products; no personal information), Sentry (error monitoring and performance tracing of our API, with request bodies, cookies, query strings and IP addresses removed), Resend (transactional email), Twilio (the SMS alerts you set up: the recipient's phone number and the alert text), Bland AI (the voice price-discovery calls you start, to a competitor store's business phone number, and their transcripts), Google (its Places service, to find a competitor store's public phone number for such a call), Firecrawl, Scrapfly, Zyte, Jina AI and SerpAPI (retrieval of public competitor web pages and search results for the products you monitor; they receive no personal information), PostHog (product analytics of our web app's page views, when switched on, and an organisation-level usage-limit event from our API; see Section 10). Full list and regional details in the Data Processing Agreement.

8. International transfers

Your primary database is hosted in the Asia-Pacific (Singapore) region; application hosting is as listed in the sub-processors in Section 7. Limited transfers occur to the United States and other regions via those sub-processors. Where the GDPR or the UK GDPR applies, the transfer of a customer's personal data to us is governed by the European Commission's Standard Contractual Clauses and the UK Addendum to them, which our Data Processing Agreement incorporates; onward transfers to our sub-processors rely on those clauses or another safeguard the GDPR recognises. A2E Group Pty Ltd is an Australian company and handles your personal information in accordance with the Australian Privacy Principles regardless of the region in which it is processed.

9. Your rights

You may access, correct, port, restrict, or delete the personal information we hold about you, and object to processing. You can ask us for a copy of your business data at any time. To exercise rights, email privacy@marginshield.io and we will respond within 30 days. If you are unhappy with how we have handled your data, you may complain to the Office of the Australian Information Commissioner (OAIC).

10. Cookies & analytics

We use first-party cookies and your browser's local storage for authentication and session management. Signing in keeps your session tokens, and your name, email address and role, in your browser's local storage. Installing or opening BAFO for Shopify also sets short-lived first-party cookies (at most 10 minutes) that hold only a random value, matched on our side against a one-way hash of it, to prove that the browser finishing a sign-in step is the one that started it.

When our product analytics is switched on, PostHog records the pages you view in our web app, each with its web address (with the secret part of a password reset, email verification, invitation or audit claim link removed, and any advertising click identifier masked), and your browser and device type, under a random identifier kept in a first-party cookie and your browser's local storage. Your browser sends PostHog its IP address with each page view, as it does to any site it contacts; our analytics runs only while our PostHog project is set to discard client IP data, so PostHog does not keep it, and we ask PostHog not to look up a location from it. Our API can also send PostHog an event when an organisation reaches its plan's product or competitor limit, identified only by the organisation, with its plan and counts. We never send PostHog your name or email address, we do not identify you to it, and we do not use it for cross-site tracking. It records nothing else: no session recordings, heatmaps, clicks, time on a page or scrolling, page titles, referring pages, screen or window sizes, language, time zone, error reports, performance timings or survey answers. You can opt out by turning on your browser's Do Not Track or Global Privacy Control setting, both of which our analytics honours: with either on, PostHog records nothing from your browser, and with Global Privacy Control on it is not started at all.

11. Children

MarginShield is a B2B platform not directed at children. We do not knowingly collect personal information from anyone under 18.

12. Changes

We may update this policy as the service evolves. We will tell the registered admin about material changes by email before they take effect. The date at the top of this page changes with every version, and a workspace that agreed to an earlier version for BAFO for Shopify is asked in the app to agree to the new one: until an owner or admin does, the workspace stays open under a notice, and BAFO keeps working under the version agreed earlier.

13. Contact

Privacy questions or requests: privacy@marginshield.io.
A2E Group Pty Ltd, Sydney, Australia.