Privacy Policy
Last updated: 2026-10-10
This Privacy Policy explains what data Darwiny ("Darwiny", "we") collects about you and, when you separately enable Darwiny experimentation services, about visitors to your storefront. What the public Shopify app accesses, and how it runs those services on a storefront, is described in section 10.
Data controller
The data controller for the purposes of GDPR is Darwiny, Flæsketorvet 68, 1. sal, 1711 Copenhagen, Denmark. Contact: support@darwiny.ai.
1. Data we collect
From merchants (you)
- Account info: email, authentication tokens, profile data.
- Billing state: Shopify handles plan approval and charges for merchants who use the public Shopify app. We retain the plan, billing-cycle dates, subscription status, and aggregate capacity-usage state needed to operate and reconcile that billing. Before Darwiny's platform-wide Shopify billing cutover is activated, eligible standalone subscriptions may be billed separately by Stripe. After that cutover, Darwiny creates no new Stripe checkout or subscription. We do not receive or store card data from either provider.
- Store metadata for services you separately enable: domain, product URLs, product titles, and images.
- Usage data: pages visited in the dashboard, feature interactions, error reports.
From storefront visitors, only when you separately enable Darwiny experimentation
- A consent-gated first-party cookie (
_dg_vid) containing a random visitor UUID. - Which variation was shown, and anonymous counters: impressions, add-to-cart, checkout, purchase.
- For order attribution, through the public Shopify app's order webhook or a separately configured Shopify webhook: the Shopify order ID, gross order total, currency, and Darwiny experiment and variation IDs needed to deduplicate and attribute orders. Shopify classifies order data as protected customer data. Since 14 October 2026, with the version of the app released that day, also the product lines of the order, refunds, and a checkout pixel's report, as described in section 10.
- Short-lived security metadata used to prevent fraudulent traffic reports: the storefront origin and an opaque one-way request-network binding. The raw network address is not included in Shopify billing events.
2. Data we do not collect
For a separately configured order-attribution integration, we retain only the minimal fields listed above, not customer names, email addresses, shipping or billing addresses, line items, or payment details. We do not fingerprint devices or share storefront visitor data with advertising networks. For the public Shopify app, read-only order access is requested for that one purpose, as described in section 10.
3. How we use data
- Operate and improve the Service.
- Manage paid Darwiny services, verify Shopify subscription entitlements, report aggregate capacity usage to Shopify, and prevent duplicate or conflicting billing.
- Send transactional emails (OTP codes, install instructions, billing receipts).
- Debug and monitor the system (error reports via Sentry).
- Aggregated product analytics (PostHog) with inputs masked by default.
4. Subprocessors
- Supabase — auth and database hosting (EU region)
- Shopify — app-plan approval, subscription billing, and aggregate usage billing for merchants who install the public Shopify app. Charges go through Shopify's Billing API: for that, the app keeps one offline Shopify Admin API token for your shop, encrypted, so that a level step can be billed while nobody has the app open. It is used for nothing else and is deleted when the app is uninstalled or Shopify sends its shop-redaction request
- Stripe — legacy standalone subscription, refund, cancellation, and payment-record processing; the public Shopify app does not use Stripe
- Resend — transactional email
- Vercel — application hosting
- Azure — worker hosting
- Sentry — error monitoring
- PostHog — product analytics (US region)
5. Data retention
Experiment, store, and account data are retained for the life of your account. Minimal order-attribution records from a separately configured integration are retained for up to 90 days; aggregate experiment counters no longer identify an order. For the public Shopify connector, we retain installation, lifecycle, and account-binding metadata, subscription snapshots, billing-cycle usage ledgers, and idempotent billing-event audit records while needed to operate the connection and meet legal accounting obligations. Payload-free traffic-event idempotency receipts are retained for no more than 90 days. Short-lived storefront authorization tokens expire after 10 minutes, and network rate-limit keys are retained only for their configured abuse-prevention windows. Disconnecting removes the account binding. Shopify privacy requests are processed through Shopify's mandatory compliance webhooks, payload-free webhook receipt metadata is retained for up to 90 days, and connector identity records are purged when Shopify sends a verified shop-redaction request. When you delete your account by emailing support@darwiny.ai we remove your data within 30 days, except where retention is required by law (e.g. invoicing records).
6. Cookies
If you separately enable storefront experimentation, then with analytics consent the Darwiny loader sets one first-party experimentation cookie on your storefront (_dg_vid) to keep a visitor on the same variation across visits and measure that variation. It is not used for cross-site tracking. With the same consent the loader may also keep a short note in the browser's local storage (_dg_early, kept for one hour) saying which product pages to show a new version of at once on the next visit; it holds page addresses and the screen width, no identifier. The dashboard uses functional cookies for authentication and session state. We respect Shopify's Customer Privacy API: if analytics processing is not allowed, the loader does not set the cookie or send experiment analytics. The public Shopify app loads that loader only while the merchant has switched on its app embed in their theme (section 10).
7. Your rights
Depending on where you live you may have rights to access, correct, port, or delete your personal data, object to processing, and withdraw consent. EU/UK residents have additional rights under GDPR/UK-GDPR. California residents have rights under the CCPA. To exercise any right, email support@darwiny.ai.
8. International transfers
We primarily host data in the EU. Some subprocessors (Stripe, Resend, Sentry) may process data outside the EU under Standard Contractual Clauses or equivalent safeguards.
9. Security
We use industry-standard controls: TLS for data in transit, encrypted storage at rest, row-level security for per-account data isolation, and scoped access tokens. Despite these measures no system is perfectly secure; you use the Service at your own risk.
10. Shopify app access
The Darwiny public Shopify app lets a merchant have new versions of a product page designed, approve a Shopify-billed Darwiny plan, and test those versions on their own storefront. It requests three read-only Shopify scopes. The read-products scope lets the embedded app display products from the currently authenticated shop so the merchant can choose which product to design pages for, and read the chosen product's title, description, options, prices, photos and star rating to design them. The read-themes scope lets Darwiny read the published theme's colour, font and button settings so the new pages match the store's look; it reads no other theme content and changes nothing in the theme. The read-orders scope is used for one purpose: receiving Shopify's order-created webhook, limited to four fields (the order identifier, its total, its currency, and its cart attributes), so that a purchase can be credited to the page version the shopper saw. The app does not use Shopify Admin APIs to read customers, checkouts, or payment data, and it does not write to the shop's products, orders, or theme files. It writes only its own app-data metafields: the linked Darwiny store identifier, a connected flag, a random verification value, a revision number, the addresses its theme app embed loads from, and the identifiers of the products that have a running test (so the embed knows, before anything is drawn, which product pages carry one). The embedded app screens do not load advertising or product-analytics trackers.
A storefront is changed only through the app's theme app embed, which the merchant switches on and off in the Shopify theme editor; the app cannot switch it on. While it is on, it loads the Darwiny loader described in sections 1 and 6. On a product page that has a running test, the loader shows either the store's own page or a Darwiny-designed version of it. With the visitor's analytics consent under Shopify's Customer Privacy API, it sets the first-party cookie described in section 6, counts page views and add-to-cart actions per version without identifying the visitor, and adds the Darwiny experiment, version, and random visitor identifiers to the cart's attributes so that a resulting order can be matched to the version. Without that consent it sets no cookie, sends no analytics, and adds nothing to the cart. It does nothing in the theme editor's preview. Switching the embed off, disconnecting the account, or uninstalling the app stops all of it. An uninstall also discards the embed's verification value, drops the app's pending work for that shop, and unbinds the shop from the Darwiny account; the account, its pages and test results, and the order-attribution records described below stay under section 5 until you delete the account, and the records that identify the connection and the attribution records still awaiting a match are removed when Shopify sends its shop-redaction request, 48 hours after the uninstall.
From each order-created webhook we keep only the order identifier, the gross order total, the currency, and the Darwiny experiment and version identifiers from the cart attributes, for up to 90 days; aggregate experiment counters no longer identify an order. The webhook subscription asks Shopify to leave out everything else, so we do not receive the customer's name, email address, shipping or billing address, line items, or payment details. An order without Darwiny cart attributes leaves only a payload-free receipt.
A merchant who is new to Darwiny gets an account made from the email address Shopify has verified for their staff login; a merchant with an existing Darwiny account connects it with the account email and a verification code. We retain the Shopify shop ID, canonical myshopify.com domain, primary domain when available, app installation ID, connection and lifecycle status, the state of the theme app embed, the linked Darwiny account/store identifiers, and one-way security hashes used for verification. The shop name is fetched to display in the embedded screen and is not stored in the connection record. Product catalog pages are returned directly to the embedded app with no-store cache controls. For a linked account, we retain one tenant-scoped snapshot containing at most the 200 most recently updated active products so the same synchronized catalog can be used in Darwiny. Each refresh replaces that snapshot, which remains bound to the exact Shopify connection and Darwiny store. Raw verification credentials are not stored.
App Bridge session tokens and request-scoped Shopify Admin tokens are used temporarily to verify the installation and shop identity, read that shop's product catalog, and write the app-data metafields above. They are not stored in our database, cookies, local storage, or browser storage. Besides the order-created webhook, the app receives only the uninstall webhook and Shopify's mandatory privacy webhooks. A mandatory privacy request may contain a request identifier and order identifiers; we use those only to locate and fulfill an access or deletion request, which removes the matching order-attribution records. We do not retain raw webhook payloads and keep only limited receipt metadata for authentication, deduplication, and compliance auditing.
The version of the app released on 14 October 2026
Since the version released on 14 October 2026, the app requests two more Shopify scopes, write-pixels and read-customer-events, which let it run one web pixel of its own on the shop. That pixel runs only for visitors who have given analytics consent under Shopify's Customer Privacy API, and it does one thing: when an order is completed, it sends Darwiny the order identifier, the checkout token, the order total and currency, and the Darwiny experiment and version identifiers from the first-party cookie described in section 6, so that an order placed without passing the cart (for example with "Buy it now" or Shop Pay) can be credited to the page version the shopper saw. It does not send the random visitor identifier, and it sends no name, email address, shipping or billing address, or payment details. We keep what the pixel sent for one day unless it is matched to an order reported by Shopify's order-created webhook; an expired record is deleted by the next clean-up, within 48 hours of its arrival.
Since the same version, the order-created webhook also carries the order's checkout token and, for each line of the order, the line identifier, the product identifier, the quantity, the price, and the discounts applied to it. We use them to credit an order only when it contains the tested product, with that product's own revenue. For a credited order we keep, with the order identifier and for up to 90 days, the tested product's identifier, its line identifiers, the units sold and their revenue; the other lines are not kept. An order that contains a tested product but arrives without Darwiny cart attributes is kept for one day (its identifier, a one-way hash of its checkout token, its total and currency, and the product identifiers, quantities and revenue of its lines) to await the pixel's report, and is then deleted by the next clean-up, within 48 hours of its arrival. We still do not receive the customer's name, email address, shipping or billing address, or payment details.
From the same version, the app also receives two more webhooks. The refund-created webhook is limited to the refund identifier, the order identifier, and for each refunded line its line identifier, quantity and amount; we use it to subtract a refund of the tested product from the page version that was credited with the order. The product-updated webhook is limited to the product's identifier and handle; it prompts Darwiny to read the product's public page again, so that page versions made from an older state of the product can be flagged to the merchant.
Shopify hosts plan selection and approval. The disclosed capacity levels per Shopify billing cycle are: USD 39 for 1 active Darwiny product and 3,000 Darwiny-tested page visits; USD 59 for up to 3 products and 10,000 visits; USD 89 for up to 10 products and 20,000 visits; USD 149 for up to 20 products and 50,000 visits; USD 299 for up to 50 products and 125,000 visits; USD 489 for up to 90 products and 300,000 visits; and USD 819 for up to 160 products with no tested-visit cap (traffic above 300,000 visits uses this level). More than 160 active products requires an enterprise arrangement and is not automatically billed through these levels.
If greater capacity is used by Darwiny services that the merchant has separately enabled, we report a Shopify shop ID, capacity event handle, event timestamp, permanent idempotency key, and aggregate capacity-level increment to Shopify's App Events API. The level is determined by whichever is higher—active-product capacity or tested-traffic capacity—so those dimensions are not added together. The highest capacity level reached during a billing cycle remains the cycle total even if usage later decreases. We do not send buyer or merchant contact data in billing events.
Before the one-way platform-wide Shopify billing cutover is activated, eligible customers who have not installed the public Shopify app may use standalone Stripe billing. Once activated, Darwiny creates no new Stripe checkout, portal, payment link, trial, subscription, or upgrade route. Existing standalone billing records remain available only for required lifecycle actions such as cancellation, refund, dispute, and payment reconciliation. An active Shopify subscription is required before a merchant can connect an account through the public app, and an unresolved standalone entitlement must be closed before connection to prevent overlapping charges. Once connected, Shopify is the sole billing authority for the app-related subscription. Optional storefront experimentation and revenue attribution remain subject to the disclosures elsewhere in this policy.
Disconnecting the Darwiny account removes the account binding only. It does not cancel the Shopify plan, reverse capacity charges already reached in the current billing cycle, or change the plan's scheduled cancellation date. Plan changes are managed through Shopify. To stop future recurring app charges, uninstall Darwiny from Shopify Admin; Shopify may still bill charges from the current cycle.
11. Changes
We may update this policy. Material changes will be announced by email at least 14 days before they take effect.
12. Contact
Privacy questions: support@darwiny.ai.