Shopify Review Technical Notes

Disclaimers

  • Luxifer and ux-pro were our old product names. Much of the architecture still references them.
  • We do NOT use level 2 customer data such as names or emails (referenced here)
  • We DO use level 1, behavior, DOM interactions, ecommerce data, demographic information, etc.

Data sent to endpoints external to Shopify

1. OpenID Connect ID Token (docs)

https://getshopifyconfigurationeu-573194387152.europe-west1.run.app

Purpose

  • When enabling tracking via the Shopify admin UI, the app.idToken()is sent to our backend in order to retrieve necessary project data. The token is used to verify that the request came from a Shopify authenticated user.

Input

  • The cloud function is public, but verifies the following
    • apiSecret must match our Shopify api secret (using jwtVerify from jose)
    • aud must match our app client id
    • exp must be after the time of call
    • nbf must be before the time of call
    • dest must exist as a URL related to one of the projects within Lummmen systems
    • Decoded and parsed payload has header and payload
  • If any of these fail, the cloud function returns a generic 401 even in the case of malformed input

Output

  • matomoId – The associated Matomo project that was created prior
  • sampple – The percentage of users tracked, for limiting throughput burden
  • name – The name of the project

Architecture

  • Shopify admin UI — Source and destination of the workflow
  • Google cloud run/firebase functions — Processing, validation & query project data
  • Firestore — Project data source

2. Matomo-based Analytics Data

https://analytics.luxifer.app

Purpose

  • Core of the Lummmen tool. Allows for the main structure of tracking (sessions).

Privacy

  • visitorConsentCollected is listened to from the document
  • consent status controls whether Lummmen can send data or not

Input

  • lummmen_site_id from a Shopify metafield (same as matomoId). Comes from admin setup (#1).
  • visitorId Hashed and truncated from window.Shopify.customerPrivacy.consentId() (docs)
  • Behavioral and Demographic data (see privacy policy #3 for details)
  • A full list of what Matomo collects can be seen here

Architecture

  • Customer browser — where the tracking code is ran
  • Self hosted Azure running Matomo — destination

Integration

  • Fires an event 'lummmen:startPixel’ so that visitorId and siteId can be visible to the pixel.
  • In case of /checkout where the liquid never renders, saves cookies with the same values.

3. Clicktracking data

https://europe-west1-ux-pro.cloudfunctions.net/processLuxiferDataEU

Purpose

  • Supplementary data that allows Lummmen users and systems to analyze customers in high granularity.

Privacy

  • visitorConsentCollected is listened to from the document
  • consent status controls whether Lummmen can send data or not

Input

  • lummmen_site_id from a Shopify metafield (same as matomoId). Comes from admin setup (#1).
  • visitorId Hashed and truncated from window.Shopify.customerPrivacy.consentId() (docs)
  • orderId and customerId for responding to privacy webhooks.
  • Mouse movements and click actions
  • Timing, location and what elements were interacted with (if clickable)
    • Element information does NOT include what is inside textboxes
    • Element information includes tag type, classnames, ids, etc.
  • see privacy policy for further details

Architecture

  • Customer browser — where the tracking code is ran
  • Google cloud run/firebase functions — Processing, validation & saving
  • Clickhouse — destination

4. Ecommerce data (Pixel only)

Purpose

  • Data that allows Lummmen users and systems to analyze customers in high granularity, track revenue and goal performance.

Privacy

  • visitorConsentCollected event from init.customerPrivacy is listened to.
  • Check is performed prior to every post request.

Input

  • customerId , orderId – used to respond to webhooks. Not always available.
  • product & variant sku, title, price, quantity, category .
  • Total prices, subtotals, taxes of orders.
  • First party cookie or custom event data from 'lummmen:startPixel’
    • siteId (same as matomoId from #1).
    • visitorId/clientId . Same as in #2.
  • url, timestamp
  • type of event from the pixel (docs)
    • checkout_completed
    • product_added_to_cart
    • product_removed_from_cart
    • product_viewed
    • collection_viewed

Architecture

  • Customer browser via pixel — where the code is ran (sandboxed)
  • Self hosted Azure running Matomo — destination

Webhooks

pubsub://ux-pro:shopify-compliance

The following webhooks are configured

Data is not deleted immediately. Instead, a request is saved and developers are notified.

The deletion process is manual, but the notification process is automatic.

Tickets for auditing

  • A Firestore document is written as a ticket in the collection gdprComplianceRequests
  • It contains the body of the webhook, the creation time, status, and platform “Shopify”
  • If resolved, it contains the resolution time and the resolver.

customers/data_request & customers/redact

  • In the case that the request only contains the customer email (like mentioned here), requests cannot be fulfilled as we do not save customer emails.
  • We save orderId and customerId in ecommerce events where available.
  • ecommerce events also have a visitorId which is the hashed consentId. (docs)
  • Using the visitorId, we can link it to and delete any data that contains this key.
  • If the data request can be fulfilled, it will be emailed to the store owner.
  • Aggregate data cannot be reasonably linked back to individuals so cannot be requested or redacted.

shop/redact

  • The redact payload has a URL which we can trace back to a project on our end.
  • This project and all of the related project data has a common key which we will use for deletion.

app/uninstalled

For the future

  • Develop a process where non-technical admins can respond to and resolve these requests.

Oh!

Il semble que vous soyez déjà abonné