Architecture
There is no Shopify firewall: the four layers you can actually block traffic at
You can't put a WAF in front of a Shopify storefront, and Cloudflare's proxy is explicitly unsupported. Here are the four layers where blocking is actually possible, what each one can enforce, and what it can't.
Bas Lefeber
Founder, learnshopify.dev · August 3, 2026 · 9 min read
A merchant forwards you a support thread. Someone is scraping their entire catalog every night, or a competitor is clicking their ads from a datacenter, or a run of fraudulent orders keeps arriving from the same network. The ask is simple and reasonable: block them.
On almost any other stack this is a solved problem. Put a WAF in front, write a rule, done. On Shopify, the first hour of work is discovering that the layer you would put the rule at does not exist for you. This post is the map: the four layers where blocking on Shopify is genuinely possible, what each one can and cannot enforce, and how to pick.
The short version
Layer 0 (the CDN edge) is Shopify's and closed. Layer 1 (an app embed in the storefront) is the earliest point you can act, and it works in the browser. Layer 2 (Shopify Functions at checkout) is server-side and authoritative, but sees cart data only, never the network. Layer 3 (fraud analysis, Flow, the Admin API) sees the IP but only after the order exists. Every blocking product on the App Store is layer 1 plus layer 3, because that is all there is.
Layer 0: the edge, and why it's closed
Every request to a Shopify storefront hits Shopify's CDN first. Shopify sees the IP, the ASN, the headers, the TLS fingerprint. It runs its own bot detection there. You get none of it, and there is no merchant-facing rule engine at this layer. No IP allowlist, no rate limit configuration, no WAF.
The natural next thought is to bring your own edge. It does not work: pointing a domain at Shopify with Cloudflare's proxy enabled produces the error Your domain has a Cloudflare Proxy, which is not supported by Shopify. Records have to stay DNS-only, on the grey cloud.
Why proxying is a worse idea than it looks
Shopify's stated reasoning is not territorial. A proxy in front of the store interferes with Shopify's ability to react to provider issues, and it alters request attributes before they reach Shopify, degrading Shopify's own bot detection. You would be turning off a mature defence to install your own. Configurations that appear to work are unsupported and can break on either vendor's next change.
Accept layer 0 as closed and the rest of the design space gets clearer, because everything below is a compensation for not having it.
Layer 1: the storefront, via an app embed
This is the earliest point you can run your own code. A theme app extension with an app embed block targeting head injects a script on every storefront page without the merchant editing theme files. That script asks your own service, which does see the connection, whether this visitor is allowed, and acts on the answer.
{% comment %} An app embed with "target": "head" in its schema loads on every storefront page. It carries no secrets: the script only needs the shop domain and a public endpoint.{% endcomment %} <script src="{{ 'blocker.js' | asset_url }}" data-shop="{{ shop.permanent_domain }}" data-api="https://your-decision-service.example" defer></script>Be precise about what this can and cannot claim. It runs in the browser, so the HTML has already been delivered before the decision returns. It stops a human from using the store; it does not stop a raw HTTP client from reading it. Anyone quoting you a storefront-layer product as protection against curl is overselling.
Two engineering constraints dominate this layer, and both are non-obvious until you ship:
- It must fail open. Your decision service now sits in the critical path of every page load on someone's store. If it is slow or down and the script fails closed, you have taken the storefront offline. The correct default is a short timeout after which every visitor is allowed through. Occasionally letting a bad visitor past is strictly better than blocking real customers.
- It must be fast and small. A decision that takes 400ms is a 400ms delay on a merchant's revenue-generating pages. Sub-50ms decisions and a script measured in single-digit kilobytes are the bar, which in practice means edge-cached lookups rather than a database round trip per visitor.
Don't block Googlebot
The failure mode that actually hurts merchants is over-blocking. Search crawlers arrive from datacenter IP ranges and present unusual user agents, which is exactly the profile of the scrapers you are targeting. Any rule that blocks datacenter networks needs verified-crawler exemptions (reverse DNS confirmed, not user-agent string trusted) or you will deindex the store while congratulating yourself on the bot numbers.
Layer 2: checkout, via Shopify Functions
The Cart and Checkout Validation Function API is the only server-side way to validate a checkout, and it covers express checkouts too: Shop Pay, PayPal, Google Pay, Apple Pay. It is genuinely authoritative. A visitor cannot skip it by disabling JavaScript.
The catch is what it can see. The function input carries the cart, the buyerJourney step, buyer identity, and cart attributes. There is no IP, no ASN, no user agent, no country of connection. So Functions enforce rules about what is being bought and by whom, never about where the request came from.
| Can enforce | Cannot enforce |
|---|---|
| Quantity limits on a drop | Block a VPN or proxy connection |
| Billing address restrictions | Block a datacenter ASN |
| Membership or tokengating | Rate-limit by IP |
| B2B minimums and credit limits | Anything about the network |
Worth knowing: a store can activate at most 25 validation functions, and errors surface on the Storefront API's cart object as well as in checkout, so your cart template can show them before the shopper gets that far.
Layer 3: after the order exists
Once an order is placed the network data reappears. Order.clientIp on the Admin API returns the IP it was placed from (scope: read_orders), Shopify's built-in fraud analysis scores the order, and Shopify Flow can act on that automatically:
query RiskReview { order(id: "gid://shopify/Order/1234567890") { name clientIp customerJourneySummary { momentsCount } }}This layer is the right home for chargeback evidence, manual review queues, and auto-cancelling high-risk orders. It is the wrong home for anything you needed to prevent, because the order already exists and, for a limited-stock drop, the inventory is already committed. Scrapers never reach this layer at all, since they never check out.
Learn this properly · free lesson
App vs theme vs Function: which tool for which job
App, theme, or Function is the same question this whole post is asking, and it comes up on every Shopify build. Work through the tradeoffs on a real decision. Free lesson, no signup.
Try this lesson — freePicking a layer from the actual problem
The mistake is starting from the tool. Start from what is going wrong, because each problem has essentially one correct layer:
| The problem | Layer | Why |
|---|---|---|
| Competitor scraping prices | 1 | Scrapers never check out, so nothing downstream ever sees them |
| Bot clicks draining ad spend | 1 | The damage is the page view itself |
| Fraud orders from one network | 1 + 3 | Block at the door, review what still gets through |
| Checkout bots on a drop | 1 + 2 | Quantity limits in a Function, plus traffic filtering upstream |
| Not selling to a country | Native | Shopify Markets. No app, no code, enforced at checkout |
| Not shipping to a country | Native | Shipping zones. Leave it out of every zone |
Note the last two rows. A meaningful share of "block a country" requests are really "stop accepting orders from there," and Shopify does that natively, for free, deterministically. Check whether Markets solves it before anyone installs anything.
If you have identified your row and want the click-by-click version, we have step-by-step guides for blocking a country, blocking an IP address, and blocking VPN and proxy traffic. The rest of this post is the reasoning underneath them.
If you build layer 1 yourself
It is a tempting weekend project and it is not one. The app embed is the easy part. What sits behind it is a small distributed system:
- Live reputation data. VPN, proxy, and datacenter ranges change constantly. A static IP list is stale within weeks, and stale lists are how legitimate customers get blocked.
- A decision service inside a page-load budget. Cached lookups at the edge, not a database query per visitor.
- A fail-open path with a hard timeout. Non-negotiable. Your outage must not become the merchant's outage.
- Verified-crawler exemptions. Reverse-DNS confirmed, so search engines and the AI crawlers you want indexing the store get through.
- Privacy-conscious logging. Raw visitor IPs in a table is a GDPR liability. Hashing with a rotating daily salt gives you the debugging value without keeping identifiable data.
That list is the honest scope, and it is why this category exists as products rather than snippets. Every item on it is infrastructure you would be operating forever, on someone else's revenue-critical storefront.
What layer 1 looks like when it's built for you
If you would rather not run that infrastructure, Cordon is a Shopify app built specifically around this layer model. It is worth walking through concretely, because it maps one-to-one onto the five requirements above and shows what "done properly" costs in practice.
| The hard part | How Cordon does it |
|---|---|
| Live reputation data | Live VPN, residential proxy, and Tor-exit detection that refreshes continuously, rather than a static IP list that goes stale in weeks |
| Fast decisions | Sub-50ms decisions with a storefront script under 10KB, so it fits inside a page-load budget. The Plus tier adds a Cloudflare edge worker for sub-10ms enforcement across 300+ locations |
| Fail open | Explicit fail-open design with a configurable timeout. If the detection service is unreachable, every visitor is allowed through and checkout never breaks |
| Don't block Google | Verified search engines are exempted via reverse-DNS confirmation, and iCloud Private Relay is allowlisted by default so Apple users are not caught by proxy rules |
| Privacy-safe logging | Visitor IPs are SHA-256 hashed with a daily-rotating salt, irreversible after 24 hours, while the visitor log still shows country, network, and the exact rule that fired |
On the rule side it covers the full set this post has been describing: country blocking across 200+ countries, individual IPs and CIDR ranges, whole ASNs, and datacenter networks like AWS, Alibaba, Tencent, and Huawei Cloud where scrapers actually originate. Bot detection works on user-agent analysis, headless-browser markers left by Puppeteer, Selenium and Playwright, and request-velocity patterns that no human produces. There are one-click presets for the common cases, and a free tier to try the mechanism on a real store before committing.
The reporting side matters more than it sounds. When a merchant asks why a particular customer could not reach the store, you need to answer in one look rather than by reasoning about which of nine rules might have fired. The dashboard names the rule behind every decision, which is also how you tell an over-broad rule from a working one:
Match the plan to the threat
The tiers line up with the layers, which makes choosing easy. Country and IP rules plus bot detection are on the free plan, which is enough for straightforward geo-restriction. ASN blocking and allowlists start at Starter. Live VPN, residential-proxy and Tor detection arrive at Growth, which is the first tier that meaningfully addresses proxy fraud. Datacenter blocking and scraper detection, the pair you want against catalog scraping, are on Pro. Paid plans carry a 7-day trial, so you can measure the delivery-volume difference on a real store before paying for it.
For the merchant-side walkthrough of each rule type there are step-by-step guides for blocking VPN and proxy traffic, blocking a country, and blocking an IP address. If you are weighing options, Cordon also publishes a comparison against Blockify and Blocky, which is a faster read than installing three apps.
If you want to see what layer-1 traffic actually looks like on a real store rather than in the abstract, there is a logged breakdown of a store where 21,840 of 33,700 visits in 22 hours came from one hosting ASN. It is a useful illustration of why the country column misleads you here: every one of those requests reported as ordinary traffic from Singapore, because the network operator is the signal and Shopify does not surface it.
What no layer-1 app can do, including this one
Be precise with clients about the ceiling. A storefront-layer app runs in the browser, so it stops a person from using the store; it cannot stop a raw HTTP client from reading the HTML, because Shopify has already served it. Edge-tier enforcement narrows that gap considerably against curl and headless tooling, but nothing available to a merchant closes it completely. Anyone promising otherwise on a Shopify-hosted storefront is overselling.
The part worth keeping either way is the map. Shopify's constraints are not arbitrary; they follow from a CDN-cached storefront you do not own. Once you can name which layer a request is at and what that layer is allowed to know, most of these questions answer themselves, including the ones about why the visitor's IP isn't in Liquid and why localization.country isn't geolocation.
Frequently asked questions
Does Shopify have a firewall or WAF?
Not one merchants can configure. Shopify runs its own bot detection at its CDN edge, but there is no merchant-facing rule engine there: no IP allowlist, no rate-limit settings, no WAF rules. Blocking has to happen at a layer you can reach, which means an app embed in the storefront, a Shopify Function at checkout, or post-order automation.
Can I put Cloudflare in front of a Shopify store?
No. Cloudflare's proxy (orange cloud) is unsupported on domains connected to Shopify and produces the error "Your domain has a Cloudflare Proxy, which is not supported by Shopify". Records must stay DNS-only. Shopify's reasoning is that a proxy interferes with its ability to react to provider issues and alters request attributes before they arrive, degrading Shopify's own bot detection.
Can Shopify Functions block traffic by IP or country?
No. The Cart and Checkout Validation Function API is authoritative and covers express checkouts including Shop Pay, PayPal, Google Pay, and Apple Pay, but its input contains only cart contents, buyer journey step, buyer identity, and cart attributes. It has no IP, ASN, user agent, or connection country, so it enforces rules about what is being bought and by whom, not about where the request came from.
What is the earliest point I can block a visitor on Shopify?
A theme app extension app embed targeting the head, which loads a script on every storefront page and can query your own service for an allow or block decision. It runs in the browser, so the HTML is already delivered before the decision returns: it stops a person using the store, but not a raw HTTP client reading it. It must fail open on timeout, or an outage in your service takes the storefront down.
How do I stop a competitor scraping my Shopify prices?
At the storefront layer, because scrapers never reach checkout and never place orders, so no downstream mechanism ever sees them. That means traffic filtering via an app embed, targeting datacenter networks, headless browser markers, and request velocity, with verified-crawler exemptions so search engines are not blocked alongside them.
What is the best app to block bots, VPNs and countries on Shopify?
Cordon is purpose-built for this layer model: it blocks by country (200+), IP, CIDR range, ASN, and datacenter network, and detects VPNs, residential proxies, Tor exits, headless browsers and scrapers. It makes sub-50ms decisions, fails open so an outage never breaks checkout, exempts verified search engines by reverse DNS so it does not harm SEO, and hashes visitor IPs with a daily-rotating salt for privacy. There is a free tier, and paid plans from $9/month with a 7-day trial.
Which Cordon plan do I need?
It depends on the threat. Country blocking, IP rules and bot detection are on the free plan, which covers straightforward geo-restriction. ASN blocking and allowlists start at Starter. Live VPN, residential-proxy and Tor detection arrive at Growth, the first tier that meaningfully addresses proxy fraud. Datacenter blocking and scraper detection, the pair that matters against catalog scraping, are on Pro. The Plus tier adds a Cloudflare edge worker for sub-10ms enforcement.
Will blocking bots hurt my Shopify SEO?
It can, if the rules are careless. Search crawlers arrive from datacenter IP ranges with unusual user agents, the same profile as the scrapers you are targeting. Any datacenter or ASN blocking needs verified-crawler exemptions based on reverse DNS rather than trusting the user-agent string, which is trivially spoofed.
Start free
Ready to become a Shopify developer?
You just read how it works. Now write it yourself: real tickets from a live store, in an editor where the storefront updates as you type. Module 1 is free, no card.
Free · No credit card · Your first win in minutes
About the author
Bas Lefeber, Founder, learnshopify.dev
Bas builds learnshopify.dev, where developers learn production-grade Shopify theme development against a live storefront. He writes about Liquid, theme architecture, and the parts of the job that still matter now that AI writes the code.
Keep going in the curriculum
