How to Build a Shopify App That Adds a Cash on Delivery (COD) Fee Automatically?
Shopify doesn’t natively support charging extra fees based on payment method (like Cash on Delivery), which can be frustrating. In this guide, you’ll learn how to build your own Shopify app that automatically adds a COD fee as a hidden product in the cart when customers select COD payment — without any subscription fees or managing your own server (using serverless and Shopify APIs).
Overview
We’ll:
- Create a hidden COD Fee product in your store
- Build a Shopify app to inject a payment method selector on the cart page
- Use Shopify AJAX API to dynamically add/remove the COD Fee product based on user selection
- Validate COD fee on order creation using Shopify webhooks
- Restrict COD payment method availability via Shopify’s native settings or Shopify Functions
Step 1: Create a Hidden “COD Fee” Product
- In Shopify Admin, create a product:
- Name:
Cash On Delivery Fee
- Price: ₹50 (or whatever fee you want)
- Set to available on your sales channels
- Optionally hide from collections and search (via theme tweaks)
- Note down the product ID and variant ID — we’ll use these in the code.
Step 2: Build a Shopify App Boilerplate
You can use Shopify CLI to create a Node.js + React app quickly:
npm install -g @shopify/cli
shopify app create node
cd your-app-name
npm install
Step 3: Inject Payment Selector on Cart Page with ScriptTag
Shopify apps can inject JavaScript into the storefront using ScriptTag API.
Create a script file in your app (e.g., public/cod-fee.js
) with:
// cod-fee.js
(async () => {
const COD_VARIANT_ID = 'your-cod-fee-variant-id'; // replace with actual variant ID
// Add payment selector UI
const cartForm = document.querySelector('form[action="/cart"]');
if (!cartForm) return;
const paymentSelector = document.createElement('div');
paymentSelector.innerHTML = `
<label>
Payment Method:
<select id="payment-method-selector">
<option value="prepaid">Prepaid</option>
<option value="cod">Cash on Delivery (+₹50 fee)</option>
</select>
</label>
`;
cartForm.appendChild(paymentSelector);
const selector = document.getElementById('payment-method-selector');
async function getCart() {
const res = await fetch('/cart.js');
return res.json();
}
async function addCodFee() {
await fetch('/cart/add.js', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({id: COD_VARIANT_ID, quantity: 1}),
});
}
async function removeCodFee() {
const cart = await getCart();
const feeItem = cart.items.find(item => item.variant_id == COD_VARIANT_ID);
if (feeItem) {
await fetch('/cart/change.js', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({id: feeItem.key, quantity: 0}),
});
}
}
selector.addEventListener('change', async (e) => {
if (e.target.value === 'cod') {
await addCodFee();
} else {
await removeCodFee();
}
location.reload(); // reload to update cart totals & UI
});
// On page load, make sure COD fee matches current selection
const cart = await getCart();
const hasFee = cart.items.some(item => item.variant_id == COD_VARIANT_ID);
selector.value = hasFee ? 'cod' : 'prepaid';
})();
Register the ScriptTag from your app backend:
// Example using Node.js Shopify API client
await shopify.scriptTag.create({
event: 'onload',
src: 'https://your-app-domain.com/cod-fee.js',
});
Step 4: Validate the COD Fee on Order Creation (Webhook)
Create a webhook in your app for orders/create
:
// Example using Express.js
app.post('/webhooks/orders/create', async (req, res) => {
const order = req.body;
const codVariantId = YOUR_COD_VARIANT_ID; // Number
const hasCodFee = order.line_items.some(item => item.variant_id === codVariantId);
if (order.gateway === 'cash_on_delivery' && !hasCodFee) {
// Log, notify, or flag order for manual review
console.warn(`COD order ${order.id} missing COD fee!`);
}
res.status(200).send('OK');
});
Register this webhook with Shopify when your app installs.
Step 5: Restrict COD Payment Method Based on Shipping Method
In Shopify Admin:
- Go to Settings > Payments > Manual Payment Methods
- Enable Cash on Delivery (COD)
- Restrict COD availability to orders using specific shipping methods, e.g. “COD Shipping”
You can add a shipping method named “COD Shipping” and instruct customers to use that.
Alternatively, you can build a Shopify Function to enforce shipping/payment logic.
Optional: Add Shipping Method COD Fee Using Shopify Functions (Advanced)
Use Shopify CLI to create a Delivery Customization Function that adds ₹50 when shipping option contains COD. See Shopify’s docs for this advanced step.
Summary
Step | What it does |
---|---|
Hidden Product | Represents the COD fee |
ScriptTag JS | Injects payment method selector on cart |
AJAX API | Adds/removes COD fee product dynamically |
Webhook | Validates COD fee on order creation |
Shopify Admin | Restricts COD payment method to specific shipping |
Final Notes
- This app does not alter checkout UI directly (Shopify limits this).
- Users select payment method early on cart page, fee is added before checkout.
- Good UX messaging is important so customers understand fees.
- Consider edge cases like fee removal, multiple tabs, etc.
Leave a Reply