Skip to main content

Shopify App Integration

What is this? A production-ready Shopify app that rewards your customers with LTZ tokens for purchases and actions in your store.

Use this if you're: Running an online store on Shopify and want to reward customer loyalty.

You'll need:


We've built a production-ready template that handles:

  • ✅ Secure Webhook Verification (HMAC-SHA256)
  • ✅ Automatic Rewards for Purchases & Signups
  • ✅ Cloudflare Workers or Node.js/Express Support
  • ✅ Simple Configuration

📦 View the Repository​

Clone the repository and follow the SETUP.md guide to get running in minutes.

git clone https://github.com/Alpha4-Labs/shopify-loyalty-app.git
cd shopify-loyalty-app
npm install
npm run dev

How It Works​

Plain English Explanation:

  1. Customer does something (makes a purchase, creates account, etc.)
  2. Shopify tells your app "Hey, something happened!" (via webhooks)
  3. Your app tells Loyalteez "Give this customer a reward!"
  4. Customer gets LTZ tokens automatically

Step-by-Step Setup​

Step 1: Deploy the App​

You can run this on any server (Railway, Heroku, DigitalOcean) or as a Cloudflare Worker (Free & Fast).

Option A: Cloudflare Workers (Recommended)

  1. Clone the repo: git clone https://github.com/Alpha4-Labs/shopify-loyalty-app.git
  2. Install dependencies: npm install
  3. Set your secrets:
    npx wrangler secret put SHOPIFY_WEBHOOK_SECRET
    npx wrangler secret put LOYALTEEZ_BRAND_ID
  4. Deploy: npm run deploy

Option B: Node.js Server

  1. Set environment variables in .env:
    SHOPIFY_WEBHOOK_SECRET=your_secret
    LOYALTEEZ_BRAND_ID=0x...
  2. Run the server: npm start

Step 2: Configure Shopify Webhooks​

  1. Go to your Shopify admin (yourstore.myshopify.com/admin)
  2. Navigate to: Settings → Notifications → Webhooks
  3. Create webhook for "Order creation":
    • Event: Order creation
    • Format: JSON
    • URL: https://your-app-url.com/webhooks/shopify
    • Click "Save"
  4. Create webhook for "Customer creation":
    • Event: Customer creation
    • Format: JSON
    • URL: https://your-app-url.com/webhooks/shopify
    • Click "Save"
  5. Copy the webhook secret and add it to your app configuration.

Shopify Webhooks Documentation Shopify Help Center guide for creating webhooks

Step 3: Test Your Integration​

We've included a Simulation UI in the app.

  1. Visit your deployed app URL (e.g., https://shopify-demo.loyalteez.app).
  2. Use the Simulate Purchase form to trigger a fake order.
  3. Check your Loyalteez dashboard to see the reward appear!

Code Example​

Here is the core logic used in the app to process orders:

/**
* Handle order creation webhook
*/
async function handleOrderCreated(order, brandId, apiUrl) {
const email = order.customer?.email;
const orderTotal = parseFloat(order.total_price || 0);

if (!email) return;

// Calculate Reward: 10 LTZ per $1 spent
const ltzAmount = Math.floor(orderTotal * 10);

// Bonus for large orders ($100+)
const bonus = orderTotal >= 100 ? 1000 : 0;

// Send to Loyalteez
await fetch(`${apiUrl}/loyalteez-api/manual-event`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
brandId,
eventType: 'place_order', // Matches your automation rule
userEmail: email,
metadata: {
order_id: order.id,
order_total: orderTotal,
ltz_earned: ltzAmount + bonus
}
})
});

console.log(`✅ Rewarded ${email}: ${ltzAmount + bonus} LTZ`);
}

Reward Strategies​

Strategy 1: Purchase Rewards (10 LTZ per $1)​

Why: Rewards every purchase, encourages repeat business. How: Default behavior in the template.

Strategy 2: Tiered Bonuses​

Why: Encourages larger orders (AOV). How:

const bonus = orderTotal >= 100 ? 1000 : 0; // 1000 LTZ bonus for orders > $100

Strategy 3: First Purchase Bonus​

Why: Rewards new customers, encourages conversion. How:

if (order.order_number === 1) {
// Send extra 'first_purchase' event
}

Interactive Widget​

The Loyalteez Interactive Widget provides customers with a full loyalty experience directly in your storefront.

Features​

  • Balance Display: View current LTZ balance
  • Streak Tracking: Daily check-in with streak multipliers
  • Perks Browsing: Browse and redeem perks
  • Daily Check-in: Customers can check in daily to maintain streaks

Installation​

  1. Create Theme App Extension:

    shopify app generate extension
    # Select: Theme app extension
  2. Add Widget Component:

    • Copy src/widget/LoyalteezWidget.tsx to your extension
    • Add to theme template where desired
  3. Configure:

    {% render 'loyalteez-widget', 
    brand_id: '0x...',
    customer_email: customer.email
    %}

Option 2: Embed Script​

Add to your theme's theme.liquid or specific pages:

<div id="loyalteez-widget" 
data-brand-id="0xYourBrandAddress"
data-customer-email="{{ customer.email }}">
</div>
<script src="https://widgets.loyalteez.app/shopify/embed.js"></script>

Widget Tabs​

Balance Tab:

  • Shows current LTZ balance
  • Displays earning opportunities

Streak Tab:

  • Current streak count
  • Multiplier display
  • Daily check-in button
  • Next milestone progress

Perks Tab:

  • Available perks list
  • Cost and availability
  • Quick redemption buttons

Daily Check-in​

Customers can check in daily to maintain streaks:

  1. Customer visits store (or widget page)
  2. Clicks "Check In Today" in Streak tab
  3. Streak recorded via shared services API
  4. Multiplier applied to next purchase reward

Implementation:

const handleDailyVisit = async () => {
const result = await fetch('/api/streak/record-activity', {
method: 'POST',
body: JSON.stringify({
brandId,
userEmail: customerEmail,
platform: 'shopify'
})
}).then(r => r.json());

// Update streak display
setStreak(result);
};

Streak System​

Streaks apply multipliers to purchase rewards:

  • 3+ days: 1.25x multiplier
  • 7+ days: 1.5x multiplier
  • 14+ days: 1.75x multiplier
  • 30+ days: 2.0x multiplier

Enhanced Webhook Handler:

async function handleOrderCreated(order, brandId, env) {
const email = order.customer?.email;
if (!email) return;

// Get user's streak for multiplier
const streakData = await fetch(
`${env.SHARED_SERVICES_URL}/streak/status/${brandId}/${encodeURIComponent(email)}`
).then(r => r.json());

const baseReward = Math.floor(parseFloat(order.total_price) * 10);
const multipliedReward = Math.floor(baseReward * streakData.multiplier);

await fetch(`${env.LOYALTEEZ_API_URL}/loyalteez-api/manual-event`, {
method: 'POST',
body: JSON.stringify({
brandId,
eventType: 'place_order',
userEmail: email,
metadata: {
platform: 'shopify',
order_id: order.id,
order_total: order.total_price,
base_reward: baseReward,
streak_multiplier: streakData.multiplier,
total_reward: multipliedReward
}
})
});
}

Perk Redemption​

Customers can redeem perks directly from the widget:

  1. Browse perks in Perks tab
  2. Click "Redeem" on desired perk
  3. LTZ deducted from balance
  4. Discount code generated (for discount perks)
  5. Code displayed to customer

Redemption Flow:

const handleRedeem = async (perkId: string) => {
if (balance < perk.cost) {
alert('Insufficient balance');
return;
}

const response = await fetch(`${SHARED_SERVICES_URL}/perks/redeem`, {
method: 'POST',
body: JSON.stringify({
brandId,
userEmail: customerEmail,
platform: 'shopify',
perkId
})
});

const result = await response.json();
if (result.success) {
// Show discount code or confirmation
showConfirmation(result.confirmationCode);
// Refresh balance
loadData();
}
};

Widget Customization​

Customize widget appearance via CSS:

.loyalteez-widget {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 20px;
background: white;
}

.widget-header h3 {
color: #8CBC99;
margin: 0 0 15px 0;
}

.widget-tabs button.active {
background: #8CBC99;
color: white;
}

Shared Services Integration​

The widget uses Loyalteez Shared Services:

  • Streak Service: /streak/record-activity, /streak/status
  • Perks Service: /perks/:brandId, /perks/redeem
  • Balance Service: Calls Loyalteez API for balance

See Shared Services Overview for details.

Show Rewards to Customers​

Add Banner to Thank You Page​

After checkout, show customers how much LTZ they earned.

  1. Go to: Shopify Admin → Settings → Checkout
  2. Scroll to: Additional Scripts
  3. Add this code:
<script>
// Get order info
const orderTotal = {{ checkout.total_price | money_without_currency }};
const ltzEarned = Math.floor(orderTotal * 10);

document.addEventListener('DOMContentLoaded', function() {
const banner = document.createElement('div');
banner.style.cssText = 'background: #8CBC99; color: white; padding: 20px; margin: 20px 0; border-radius: 8px; text-align: center;';
banner.innerHTML = `
<h2 style="margin: 0 0 10px 0;">🎉 You Earned ${ltzEarned} LTZ!</h2>
<p style="margin: 0;">Your rewards have been added to your wallet.</p>
<a href="https://marketplace.loyalteez.app" style="color: white; text-decoration: underline;">View Your Wallet →</a>
`;

const container = document.querySelector('.main-content') || document.body;
container.prepend(banner);
});
</script>

Troubleshooting​

"Webhooks aren't being received"​

Check:

  1. Is your server running and accessible?
  2. Did you configure webhooks in Shopify admin?
  3. Is the URL correct in Shopify settings?

"Events track but no LTZ given"​

Check:

  1. Is your Brand ID correct?
  2. Are reward rules configured in Partner Portal?
  3. Check Partner Portal analytics for the event.

"Getting 401 Unauthorized errors"​

Check:

  • Ensure your SHOPIFY_WEBHOOK_SECRET matches the one in your Shopify Admin.

Support​