Tom Sailors
Brief · Anonymized case study

Fraud-Resistant Referral Rewards Engine

I'd build this as a four-part system: generate a unique referral code per customer and store it in a metafield so they can share it; use Shopify Flow to tag new customers who arrive via that code and verify it's truly a first order; apply store credit automatically via a Discount Function when the referred order clears minimum thresholds; and surface everything in a simple customer dashboard where they can see their link, referral count, and credit balance. The whole stack lives on Shopify—no external referral app needed.

A DTC merchant wanted to build a customer referral program that rewarded existing customers with store credit when their friends placed a first order, without relying on third-party app-store dependencies. The challenge was preventing fraud (gaming with fake accounts or repeat signups) while keeping the entire flow within Shopify's native tooling.
Four pieces
Marketing

Referral Link Generator

Generates a unique referral code for each customer and stores it in a metafield. The customer can retrieve and share their code via a dashboard or customer account page.

Custom Shopify app + Shopify metafield
Admin GraphQL explorer graphql
# Admin GraphQL
mutation GenerateReferralCode($customerId: ID!) {
  metafieldsSet(metafields: [
    {
      ownerId: $customerId
      namespace: "referral"
      key: "referral_code"
      type: "single_line_text_field"
      value: "REF_12345ABCDE"
    }
  ]) {
    metafields {
      id
      value
      namespace
      key
    }
    userErrors {
      field
      message
    }
  }
}

query GetReferralCode($customerId: ID!) {
  customer(id: $customerId) {
    id
    email
    metafield(namespace: "referral", key: "referral_code") {
      value
    }
  }
}
Generate a unique code per customer (use UUID or timestamp + hash); store it in a metafield so you can retrieve and display it in a dashboard later.
Customer Verification

Referee Tracker

Watches for new customers arriving via a referral code and verifies it's a first order before tagging them and logging the referral relationship. Fires a webhook to the backend when a valid referral is detected.

Shopify Flow + custom order tag
Shopify Flow editor: When → Then flow
Trigger: Order is created

Condition: Order source contains referral code query param (extract via Flow or store in cart attribute beforehand)
  AND customer is placing their first order (check customer.orders.count = 1)
  AND order contains at least one product line item (prevent gaming with empty orders)

Action 1: Tag customer with "referred-by-[referrer_code]"

Action 2: Tag customer with "first_order_confirmed"

Action 3: Send event to custom app webhook: { referrer_code, referee_email, order_total, timestamp }
  (Webhook payload triggers the referrer credit issuance in the next piece)
The referral code must be stored in the cart or customer session before checkout (usually via URL query param that the app reads and stores as a cart attribute).
Operations

Credit Payout Gate

When a verified referral converts, automatically applies store credit to the referrer's account. Includes safeguards: only credits if the order meets a minimum threshold, and prevents duplicate payouts for the same referral.

Custom Shopify app backend + Shopify Function
extensions/discount/src/run.graphql function
# Function input query — Discount Function
query Input {
  cart {
    buyerIdentity {
      customer {
        id
        email
        metafield(namespace: "referral", key: "available_credit") {
          value
        }
      }
    }
    cost {
      totalAmount {
        amount
      }
    }
  }
}
This queries the customer's stored referral credit balance (updated by your backend when a referral converts). Your Discount Function runtime then applies it as an automatic discount at checkout.
Storefront

Referral Dashboard

Displays each customer's unique referral link, total friends referred, pending and earned credit balance, and a copy-to-clipboard button. Embedded in the customer account page or as a dedicated page.

Theme app extension + React
theme/snippets/referral-dashboard.liquid liquid
{% if customer %}
  <div class="referral-dashboard">
    <h2>Your Referral Link</h2>
    
    {% assign referral_code = customer.metafields.referral.referral_code %}
    {% assign credit_balance = customer.metafields.referral.available_credit | default: 0 %}
    {% assign referrals_count = customer.tags | where: "referred-by-" | size %}
    
    {% if referral_code %}
      <p class="referral-url">
        {{ shop.url }}/pages/checkout?ref={{ referral_code }}
      </p>
      <button onclick="copyToClipboard(this)">Copy Link</button>
    {% endif %}
    
    <div class="referral-stats">
      <div class="stat">
        <strong>Friends Referred</strong>
        <span>{{ referrals_count }}</span>
      </div>
      <div class="stat">
        <strong>Available Credit</strong>
        <span>${{ credit_balance | default: 0 }}</span>
      </div>
    </div>
  </div>
{% else %}
  <p>Sign in to see your referral rewards.</p>
{% endif %}
Render this on a dedicated page or in account sidebar. The referral code URL param is picked up by your app on the landing page and stored in the cart before checkout.

Got a similar problem?

Sketch your build in 30 seconds — voice, type, or attach a screenshot.

Sketch the build →