Connect Shopify (Preview)

Preview · Available to selected organizations. Connect a Shopify store to Samva from the Settings page in your organization's dashboard.

Connecting a Shopify store links it to your Samva organization. Connect and disconnect from Settings → Integrations in the dashboard, let an agent use it to answer order questions, and start journeys from store activity. This page is available in Preview.

Connect from the dashboard

Open Settings in your organization's dashboard, choose Integrations, and locate the Shopify card.

  1. Enter your store's .myshopify.com domain in the Shop domain field, for example your-store.myshopify.com.
  2. Choose Connect. Samva redirects your browser to Shopify to authorize the connection.
  3. Approve the requested access in Shopify. If the app is already installed, Shopify can return you directly to Samva. The Integrations page confirms the connection.

The Integrations page shows the shop domain, who connected it, the connection date, and a Disconnect button.

Connect after installing in Shopify

Open Samva from Shopify after installing the app. Sign in to Samva if prompted. Samva opens Settings → Integrations in your last-used organization, or your first organization if you have not selected one, with the shop domain filled in.

Check that you are in the organization you want to connect. An organization administrator must choose Connect and finish authorization before the store is connected to Samva.

Connect from the API

The connect endpoint is gated behind the agents permission resource and requires an organization administrator. The OAuth callback that finishes the connection requires the same administrator's active dashboard session; an API key alone cannot complete it. Use the dashboard to connect a store.

If your workflow starts the flow programmatically, the endpoint is POST /v1/integrations/shopify/connect. Supply the returnTo field as a root-relative dashboard path, for example /dashboard/acme/settings/integrations, not an absolute URL.

Let an agent answer order questions

After the store shows as connected, open the agent's Connect step and switch the store on. The agent can then look up order status, tracking, delivery date, and refunded amount, and tell the customer how long they have to return an order. See Answer order questions from Shopify for what the agent can and cannot do.

  • Sender only. The agent looks up orders for the address that emailed in. It cannot search other customers, and an order number that belongs to someone else returns nothing. The sender authentication requirements also apply to replies using earlier order details.
  • Read only. The agent never cancels, refunds, or creates returns. It hands those requests to a person.
  • Return window and order history. See the lookup limits for how the return deadline is calculated and which orders are available.

Start journeys from store activity

A connected store records contact events as customers buy, receive, and return orders. A journey starts from one of these events the same way it starts from a custom event, with an event trigger and the event's name. The store's customer becomes a contact, identified by email.

EventRecorded when
shopify.order_createdA customer places an order
shopify.order_fulfilledThe store fulfills an order
shopify.order_deliveredA shipment first shows as delivered
shopify.refund_createdThe store refunds an order
shopify.checkout_startedA checkout first has a usable email, on creation or update

Order events carry an order object and the shop. Checkout events carry a checkout object and the shop.

PropertyMeaning
order.nameThe order number the customer sees, for example #1042
order.totalThe order total as a decimal string
order.currencyThe order's currency code
order.statusUrlAn optional order status link; may be null
order.items[]Each line: title, quantity, price, and imageUrl
checkout.checkoutUrlA link that returns the customer to their checkout
shopThe store's .myshopify.com domain

A checkout carries total, currency, and items[] like an order. Events leave out addresses and phone numbers. An order with many lines carries the first lines only. order.statusUrl is null when no authorized link is available; templates must handle a missing link. A journey email reads these values as event.*; declare event in the template's input schema, as described in Send an email. Item prices are decimal strings; quantities are numbers. Image and status links are null when unavailable.

Each delivery from Shopify records at most one event, so a retried delivery does not start a second run. A checkout records shopify.checkout_started once per store and checkout, at the first create or update with a usable email. Opening a guest checkout without an email records nothing; later updates do not start another run after the event is recorded.

Each event finds or creates a contact by email. Order events use the order's email, falling back to the customer's current email when the order has none. The Shopify customer GID is assigned as externalId only when the recipient matches the customer's current email. An update for an older order keeps its original recipient without moving that GID back to a previous contact. Samva also updates contacts when customer details change in Shopify. Previous contact history stays separate.

Samva preserves externalId values set manually or by another store. If an existing key prevents a Shopify GID assignment, the event still records against the contact matched by email.

Marketing consent follows the customer's email subscription in Shopify:

Shopify subscriptionIn Samva
SubscribedThe contact gets the tag shopify-subscribed
UnsubscribedThe tag is removed and the contact is opted out of email
Not subscribedNo change

Consent updates are ordered separately for each Shopify customer and email address. Subscribing never removes a Samva email opt-out. A customer who never subscribed can still enter post-purchase journeys. Email opt-outs and other suppressions still apply. Branch on the shopify-subscribed tag before sending marketing.

Recipes

Each recipe creates a journey with the SDK. Templates named here are templates you publish first. Publish the journey with journeys.publish as shown in Create and publish a journey.

Post-purchase check-in. Send a thank-you, wait three days, then ask how the order is going.

post-purchase-check-in.ts
import { createClient } from "samva";

const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });

await samva.journeys.create({
  name: "Post-purchase check-in",
  definition: {
    trigger: { type: "event", eventName: "shopify.order_created" },
    rootNodeId: "thanks",
    nodes: {
      thanks: {
        type: "send_email",
        config: { template: "order-thanks" },
        next: [{ nodeId: "pause" }],
      },
      pause: { type: "wait", config: { durationSeconds: 259200 }, next: [{ nodeId: "check-in" }] },
      "check-in": {
        type: "send_email",
        config: { template: "order-check-in" },
        next: [{ nodeId: "done" }],
      },
      done: { type: "exit", config: {}, next: [] },
    },
  },
});

Return-window reminder. Start when the shipment is delivered, wait for most of the return window, then remind the customer how to return. Set the wait to match your store's actual return policy; this example waits five days.

return-window-reminder.ts
await samva.journeys.create({
  name: "Return-window reminder",
  definition: {
    trigger: { type: "event", eventName: "shopify.order_delivered" },
    rootNodeId: "pause",
    nodes: {
      pause: { type: "wait", config: { durationSeconds: 432000 }, next: [{ nodeId: "remind" }] },
      remind: {
        type: "send_email",
        config: { template: "return-window-reminder" },
        next: [{ nodeId: "done" }],
      },
      done: { type: "exit", config: {}, next: [] },
    },
  },
});

Checkout reminder. Start when a customer begins a checkout and wait for an hour. If the contact orders in that time, exit. Otherwise remind contacts tagged shopify-subscribed and exit for everyone else.

checkout-reminder.ts
await samva.journeys.create({
  name: "Checkout reminder",
  definition: {
    trigger: { type: "event", eventName: "shopify.checkout_started" },
    rootNodeId: "wait-for-order",
    nodes: {
      "wait-for-order": {
        type: "wait_for_event",
        config: { eventName: "shopify.order_created", timeoutSeconds: 3600 },
        next: [
          { nodeId: "done", outcome: "matched" },
          { nodeId: "consent", outcome: "timed_out" },
        ],
      },
      consent: {
        type: "branch",
        config: {},
        next: [
          {
            nodeId: "remind",
            condition: {
              match: "all",
              predicates: [{ type: "tag", tag: "shopify-subscribed", present: true }],
            },
          },
          { nodeId: "done" },
        ],
      },
      remind: {
        type: "send_email",
        config: { template: "checkout-reminder" },
        next: [{ nodeId: "done" }],
      },
      done: { type: "exit", config: {}, next: [] },
    },
  },
});

The reminder template links to event.checkout.checkoutUrl.

Limits

  • A contact has one live run per journey. A customer who orders again while their post-purchase run is active does not start a second run, and a customer is not re-enrolled unless the journey sets reentry to true.
  • wait_for_event matches the event by name for the contact. Any shopify.order_created after the wait begins counts, including an order unrelated to the checkout.
  • Branches test tags, contact properties, custom fields, and whether an event occurred. They cannot test an event's properties, such as an order's total or its items.
  • Events are recorded only while journeys are available for your organization and the store is connected.

Store ownership

A Shopify store connects to one Samva organization at a time. If you supply an existing integrationId in the connect request, Samva reconnects that integration rather than creating a new one.

Reconnection

Samva refreshes the Shopify access token automatically. If Shopify revokes the access or the refresh credential expires, the integration status changes to Needs reconnecting. Open Settings → Integrations, choose Reconnect, and complete the authorization flow. The shop domain, return-window setting, and connection history are preserved.

If Samva cannot confirm that Shopify finished connecting the store, connection and disconnect attempts are refused briefly. Wait a minute, then connect again.

Disconnect

Disconnect removes the integration and its saved access from Samva. For a working connection, Samva also asks Shopify to uninstall the app. If the connection needs reconnecting or Shopify is unavailable, uninstall Samva in Shopify Admin to remove the app there.

If Samva cannot confirm that Shopify finished uninstalling, disconnect fails and reconnection stays blocked. Contact Samva support to verify the uninstall before reconnecting.

Disconnect retains contacts, commerce events, and journey history. Shopify privacy requests still erase the store's attributed history after the connection is removed.

To disconnect through the API, send a DELETE to the integration's own URL. The request carries no body:

Disconnect
curl -X DELETE https://api.samva.dev/v1/integrations/intg_… \
  -H "x-api-key: $SAMVA_API_KEY"

Uninstall

Uninstalling the Samva app from your Shopify Admin marks the integration as Needs reconnecting and retains the integration record. Shopify later sends a shop/redact request to remove the saved data for that uninstalled connection. If you reconnect first, a delayed request for the earlier uninstall preserves your working connection and its attributed contact, commerce, and journey history.

Privacy requests

Samva acknowledges customer data requests (customers/data_request) from Shopify within the required window.

When Shopify sends customers/redact, Samva deletes that customer's shopify.* contact events in every Samva organization that retains history from the addressed store, clears names and externalId values still assigned by that Shopify customer, and removes their shopify-subscribed tags. Shopify can identify the customer by ID or email; the ID takes precedence when both are present. An email-only request includes matching guest activity and Shopify customer history across email changes. Explicitly listed orders are erased even when the request has no usable customer ID or email.

The contacts, fields you have replaced, and non-Shopify history remain. Email opt-outs and other suppressions remain to protect recipients from unwanted email. Matching event data stored in journey history is cleared, including copies whose original event has expired; the journey records remain. Previously rendered or sent emails and conversation history are not deleted. Delayed activity from before the erasure request cannot restore the erased data. Activity without a usable Shopify timestamp is ignored after erasure. New activity after the request can record customer data again, with existing email opt-outs still applied. Erased orders and checkouts cannot be restored. Later updates to an erased checkout do not start another checkout reminder.

Samva retains the store-to-organization association and hashed erasure markers and email-to-customer associations so later erasure requests can still find Shopify history after disconnect.

For a confirmed uninstall or a disconnected store, shop/redact removes any remaining Shopify connection and erases all of that store's commerce events, Shopify-assigned contact fields and subscription tags, and copied journey entry data. Contacts, fields you have replaced, history from other stores, imported contact history, topic subscriptions, and email opt-outs remain. Customer and store erasure requests work even when the store is disconnected or commerce events are unavailable for your organization. Hashed erasure records remain to prevent delayed activity from restoring erased data.

Samva reads the store's name and .myshopify.com domain once during connection to verify the shop identity. Order lookups and journey events read current Shopify data. Commerce events store the projected order or checkout fields on the contact's event history; customer updates store the contact's name and Shopify customer ID. The returned order details appear in the conversation's tool-action history and may be included in the agent's reply.

Related documentation

On this page