更新日時

Beyond Drag-and-Drop: Programming Complex Logic in Shopify Flow

Hi, I’m Rossella, a Frontend Developer at Flagship. In this article, I’ll share a real-world example of how we used Shopify Flow not just as an automation tool, but as a powerful development platform.

Shopify powers millions of online stores, from solo entrepreneurs to Fortune 500 brands. As an e-commerce platform, it offers standard features out of the box (product catalogs, shopping carts, payment processing), but its real power lies in extensibility. Developers can build custom storefronts, integrate external APIs, and create sophisticated business logic through apps and integrations.

One of Shopify's native tools is Shopify Flow, a free automation engine built into the platform. On the surface, Flow appears to be a no-code solution. You drag and drop triggers, conditions, and actions to build workflows. For example, tag customers when they spend over $500, send an email when inventory runs low, auto-fulfill orders to specific warehouses.
These visual builders make common e-commerce automations accessible to non-developers.

But Flow has a feature that most users never discover: the Run Code action. This single capability transforms Flow from a simple automation tool into a hybrid development platform where real programming meets visual workflow coordination. You can write JavaScript directly inside a Flow step, keeping Shopify's infrastructure while adding custom logic exactly where you need it.

It’s a way to build enterprise-level logic while staying within Shopify's native ecosystem, with direct access to customer data, orders, and the full Admin API.

Here's how we used it to solve problems that typically require custom backend infrastructure (complex calculations, state management across multiple systems, and integration with external APIs), all through Shopify Flow.

Complex State Management Meets External Integration

The project: build a customer membership system that integrates with an external platform. The external API calculates customer tiers and allocates benefits. Shopify needed to consume this data, display it, track benefit usage across multiple storefronts (Online Store and Shopify POS), and keep every state change consistent across systems.

The system required time-based prioritization logic (which year's allocation to consume first), multiple resource types with different consumption rules, year-end rollover automation, and complete audit trails. It needed to deploy across multiple Shopify instances with regional variations—different markets required different benefit application methods while maintaining consistent core logic. And everything had to happen in real-time, with customer-facing displays reflecting current state instantly and no acceptable delay between actions and data updates.

The question wasn't technical, it was architectural: build custom infrastructure, or leverage Shopify's native capabilities?

The Decision Framework: Build vs. Platform

A custom backend would give complete control but meant infrastructure management, deployment pipelines, and ongoing maintenance. Shopify's native tools offered faster deployment and automatic scaling—but could they handle this complexity?

Standard Flow actions handle simple operations, but complex calculations, JSON manipulation, and conditional logic across multiple metafields require real programming.

That's where Run Code comes in.

Validating the Approach

Before committing to the architecture, we built a series of small proof-of-concept Flows.

We weren’t trying to solve everything. We just needed to answer a few specific questions:

  • Can Run Code handle complex JSON?
  • Can we implement LIFO logic reliably?
  • Can we pass structured outputs into subsequent Flow steps?
  • Can we query everything we need via GraphQL?

Once those worked, the decision became much clearer.

The architecture decision: 
The platform already provided 80% of what we needed, and Run Code could fill the gap for complex logic that visual builders couldn't handle.

What We Built: High-Level Architecture

The solution used Flow end-to-end, both its visual builders and its programming layer.

Visual actions handled workflow coordination: triggering on events, branching based on conditions, executing standard operations like writing metafields or adding tags. Run Code actions handled the complex logic: LIFO consumption algorithms, JSON manipulation for audit trails, state calculations across multiple metafields, hash functions for unique discount codes.

Customer metafields stored everything (benefit balances, usage history, tier information), accessible to both Flow workflows and the theme layer. A single source of truth for customer benefit status.

No external database, no custom backend. Just Shopify, pushed a bit further than usual.

Working Within Platform Constraints

Shopify Flow isn't perfect. We encountered real limitations that required creative solutions.

The metafield trigger problem. Flow can't trigger directly on metafield changes. When the external API updated customer benefit allocations, Flow had no native way to react. The solution: customer segments as change detection. When the metafield changed, customers entered or exited segments, triggering Flows. Not ideal, but it worked. The pattern we discovered: segments can effectively "listen" to metafield changes, even if that's not their primary purpose.

Testing with corrupted state. Flow's test mode uses current store state. When a buggy Flow run corrupted customer data (for example editing a metafield as a result of the action), testing the subsequent fix became impossible—the test would use already-wrong values as input. We needed clean data to validate the corrected logic.

The solution:

  • Extract the various Run Code actions to GitHub repositories
  • Create test scripts with sample JSON data representing customer and order data before the bug occurred
  • Test the logic in terminal, deploy only when verified

The unexpected benefit: version control for Flow logic and a complete development history. These weren't hacks. They were patterns that emerged once we understood the platform’s limits.

The Strategic Lens: Knowing When Not to Code

The real skill in platform development isn't just writing code. It's knowing when not to write it.

Flow's visual actions already handled 80% of what we needed: workflow coordination, conditional logic, metafield updates, tag management, API calls. Run Code filled the 20% gap—the business logic that visual builders couldn't express. LIFO algorithms, state calculations, audit trails. All within the same platform.

A custom backend would have worked, but it would have meant building and maintaining infrastructure that Flow already provides.

The most interesting part of this project wasn't the code. It was realizing how much we didn't need to build from scratch. Flow gave us the orchestration, storage access, and scaling. Run Code let us add custom logic exactly where needed, without leaving the platform.

The hard part isn't "Can I build this?"
It's knowing when not to.