# Developer guide (/platform/developers)

The parts of the stack every product shares. Product-specific setup lives with each product: [YourSizer widget](/yoursizer/integrations/script-tag), [ResReturn integration](/resreturn/integration) and [NoShot publishing](/noshot/publishing).

## Product identity [#identity]

The widget identifies the product from the page address: it asks whether the current URL belongs to a product in your YourSizer catalogue, and only then shows the button. Every recommendation, chart lookup and analytics row hangs off that match — a product page that cannot be matched simply gets no button, and a page matched to the wrong product looks healthy and is quietly wrong.

**Rules**

- The product URL in your catalogue must be the address shoppers actually land on.
- Use the platform’s canonical product id in the catalogue feed.
- Keep the id stable across locales and currencies.
- Variant ids belong in the size mapping, not in the product id.
- On Shopify, language prefixes such as `/en/products/…` and collection paths resolve to the same product.

<Callout title="Canonical URL normalisation">
  Where a product is identified by URL, we normalise it before matching: host lower-cased, query string and fragment stripped, trailing slash and default port removed. Two URLs that differ only in tracking parameters are the same product.
</Callout>

### Conversion signal chain [#conversion-signal-chain]

Linking an in-widget interaction to a completed order runs through a chain of independent signals, tried in priority order, rather than one cart attribute. Storefronts and checkouts strip metadata in ways you cannot predict, and a single-signal design fails silently — the number stays plausible and just gets smaller.

| Priority | Signal | Survives |
| --- | --- | --- |
| 1 | Explicit cart attribute / line-item property | Platforms that preserve cart metadata through checkout |
| 2 | Cart token captured at interaction time | Attribute stripping, custom checkouts |
| 3 | First-party client id cookie | Cart rebuilds, session restarts on the same device |
| 4 | Client id in a first-party store | Cookie loss within the same browser profile |
| 5 | Coarse network + product match within a window | Last resort; reported separately and never merged blindly |

Every attributed order records which signal proved it, and the dashboard deduplicates across the chain so one order can never be counted twice.

## Data & privacy [#privacy]

<Cards>
  <Card title="What we store">
    - Body model values the shopper entered or adjusted
    - The recommendation produced, and the chart version it was produced against
    - Interaction events for analytics
    - For returns: the order data required to run the return, fetched from your platform
  </Card>
  <Card title="What we do not require">
    - A photo or a body scan for sizing
    - A shopper account to use the return portal
    - Payment credentials — refunds are executed by your platform, not by us
  </Card>
  <Card title="Isolation">
    Merchant data is separated at several layers — storage, query filtering, row-level policy and explicit tenant parameters on ingest — so one store’s data cannot be reached from another’s session. Platform webhooks are validated against the store they claim to come from.
  </Card>
  <Card title="Retention and erasure">
    Body measurements are treated as personal data under GDPR and KVKK: defined retention, soft delete, and a right-to-erasure path. Platform data-deletion and uninstall webhooks are implemented, not stubbed.
  </Card>
</Cards>

<Cards>
  <Card title="Platform coverage" href="/platform/coverage" />
  <Card title="Ask a technical question" href="/platform/company" />
</Cards>
