How to Sync Revel POS Menu Items into a Shopify Online Store

Build a Spojit workflow that reads your Revel POS products on a schedule and creates or updates the matching Shopify products, so your online ordering storefront always mirrors the in-store menu.

What This Integration Does

When you add a new dish, retire a seasonal item, or correct a price in Revel, your Shopify storefront should reflect it without anyone re-keying data. This workflow keeps Shopify in step with Revel automatically: it pulls the current Revel product catalog, finds the matching Shopify product for each item, and either updates it in place or creates it if it does not exist yet. The result is an online menu that stays accurate to the point-of-sale system your staff already maintain, which cuts double entry and prevents customers from ordering items you no longer sell.

The run model is a scheduled, one-directional sync from Revel to Shopify. A Schedule trigger fires on a cron expression (for example every morning, or every few hours), reads the Revel products, and loops over them. Each item is matched to Shopify by a stable key (a tag carrying the Revel product ID), then upserted: existing products are updated, new ones are created as drafts for review. The sync is idempotent: because matching is keyed on the Revel ID rather than blindly creating, re-running the workflow does not produce duplicate Shopify products. It leaves Shopify as the read side; nothing is written back to Revel.

Prerequisites

  • A Revel connection added under Connections - Add connection, authorized against your Revel establishment, so the Revel connector tools are available.
  • A Shopify connection with permission to read and write products (product create, update, and read scopes).
  • A decision on your match key. This tutorial tags each Shopify product with revel-id:{{ ... }} so the workflow can find it again on the next run. Pick this convention before you start and keep it consistent.
  • An understanding of which Revel fields map to which Shopify fields (name to title, price, category to product type, etc.). Revel product fields vary by establishment, so confirm yours in a single get-product call first.

Step 1: Start the workflow on a Schedule trigger

Add a Trigger node and set its type to Schedule. Enter a 5-field Unix cron expression and an IANA timezone. For a daily early-morning sync in Sydney, use:

Cron:     0 6 * * *
Timezone: Australia/Sydney

A single Schedule trigger can hold multiple schedules if you want, for example a frequent sync during opening hours plus an overnight catch-up. The trigger output is {{ scheduledAt }}, which you can reference later for logging. Start with a wider interval (once or twice a day) while you validate, then tighten it.

Step 2: Read the Revel product catalog

Add a Connector node in Direct mode, choose the Revel connector, and select the list-products tool. Key inputs:

  • limit - number of results per page (default 20). Set this to a comfortable page size such as 100.
  • offset - the pagination offset; leave blank for the first page.
  • active - set to true to sync only items currently active in the POS.
  • ordering - an optional sort field if you want a deterministic order.

If your menu is larger than one page, repeat this call with an increasing offset (see the pagination pitfall below). Bind the output to a variable such as revelProducts so downstream nodes can read it as {{ revelProducts }}.

Step 3: Loop over each Revel product

Add a Loop node in ForEach mode and point it at the product list from the previous step (for example {{ revelProducts.items }}, matching the field your Revel result exposes). Each iteration gives you one product as {{ item }}. Everything in Steps 4 through 6 lives inside this loop body, running once per menu item. Keep the loop body lean so a large catalog does not blow out the run time; you can raise the schedule frequency later rather than processing thousands of items in one pass.

Step 4: Find the matching Shopify product

Inside the loop, add a Connector node in Direct mode for the Shopify connector and select list-products. Use Shopify's search syntax in the query field to look up the product by the Revel-ID tag you assign on write:

query: tag:revel-id-{{ item.id }}
first: 1

Bind the result to shopifyMatch. The presence or absence of a returned product is what the next step branches on. Using a tag as the match key keeps the lookup stable even if the dish is renamed in Revel, because the tag never changes while the Revel product ID stays the same.

Step 5: Branch on whether the product already exists

Add a Condition node that checks whether shopifyMatch returned anything, for example testing that the matched products array length is greater than 0. The true branch handles an existing product (update); the false branch handles a new one (create). Optionally, before this branch, drop a Transform node to shape the Revel fields into the exact Shopify fields once, so both branches read from a single clean object such as {{ mapped.title }}, {{ mapped.productType }}, and {{ mapped.descriptionHtml }}. Keeping the mapping in one Transform avoids drift between the create and update payloads.

Step 6: Update an existing product (true branch)

On the true branch, add a Connector node in Direct mode for the Shopify connector and select update-product. Pass the matched product's ID plus the mapped fields:

id:           {{ shopifyMatch.products.0.id }}
title:        {{ item.name }}
productType:  {{ item.category }}
status:       ACTIVE
tags:         ["revel-id-{{ item.id }}"]

Note that tags on update-product replaces all tags, so include the revel-id- tag every time or you will lose your match key. The status enum accepts ACTIVE, DRAFT, or ARCHIVED: set retired Revel items to ARCHIVED if you prefer to hide rather than update them.

Step 7: Create a new product (false branch)

On the false branch, add a Connector node in Direct mode for the Shopify connector and select create-product. New products default to DRAFT, which is useful: it lets a team member review the imported item (price, image, description) before it goes live online.

title:        {{ item.name }}
productType:  {{ item.category }}
descriptionHtml: {{ item.description }}
status:       DRAFT
tags:         ["revel-id-{{ item.id }}"]

The revel-id- tag you write here is exactly what Step 4 searches for on the next run, which is what makes the sync idempotent and keeps it from creating duplicates. If you would rather publish new items immediately, set status to ACTIVE instead. You can also drop a Send Email node after the create branch to notify your team that new draft products are waiting for review, templating the menu item name into the body.

Tips

  • Run the heavier read once. Call Revel list-products a single time per run and loop in memory rather than re-querying Revel for every item.
  • Keep create payloads as drafts at first. Importing as DRAFT gives staff a chance to add photos and polish descriptions before customers see the item.
  • Use Miraxa, the intelligent layer across your automation, to scaffold this quickly. A prompt like "Add a Loop over the Revel product list, then a Condition that checks if a Shopify product with tag revel-id exists, with update and create branches" sets up the skeleton, then fine-tune each node in the properties panel.
  • If your Revel and Shopify category names differ, add a small Transform mapping table so POS categories land in sensible Shopify product types.

Common Pitfalls

  • Pagination cut-off. Revel list-products returns one page (default 20). If your menu is larger, raise limit and page through with offset, or you will silently sync only the first page.
  • Tag replacement on update. Shopify update-product replaces all tags. Always re-include revel-id-{{ item.id }} in the update payload, otherwise the next run cannot find the product and creates a duplicate.
  • Timezone confusion. The Schedule trigger cron runs in the IANA timezone you set, not your browser's. A "6am daily" sync only lands at 6am local if the timezone is correct.
  • One-way only. This workflow writes to Shopify and never back to Revel. Treat the POS as the source of truth and avoid editing the synced products directly in Shopify, or your edits will be overwritten on the next run.

Testing

Before relying on the schedule, validate on a tiny scope. Temporarily set the Revel list-products limit to a small number (or filter by name to a single test dish), then use the Run button to execute the workflow manually. Confirm in Shopify that the test item was created as a draft with the correct revel-id- tag, title, and product type. Run it a second time and confirm no duplicate appears and that the existing product is updated instead. Once the create and update branches both behave, remove the test filter and let the Schedule trigger take over.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.