Restrict a store to specific IP addresses
On this page
Use the theme controller to limit a store to a list of IP addresses, so only your team and your client can see the storefront before launch. Visitors from any other address are redirected to a holding page.
Choose how to limit access
StoreConnect has three ways to keep a store out of view. They differ in who can open the store.
| Option | Who can open the store | Search and AI engines | Partial access |
|---|---|---|---|
| Stealth mode | Anyone with the URL | Asked not to index the store. Compliant crawlers follow the request, but it is not enforced | No. Applies to the whole store |
| Disable the store | No one. Every visitor sees the disabled content block | Nothing to index | No. There is no exception for an IP address or a user |
| IP restriction (this article) | Only the IP addresses you list. Everyone else sees the holding page | Not affected. Turn on stealth mode as well | Yes, with a path condition |
The check in this article uses the visitor’s IP address. You can test other request attributes the same way, such as the visitor’s country with current_request.geolocation_country_code, by changing the condition in the controller.
Before you start
- You need edit access to the Theme your store uses, so you can create a Theme Template on it. See theme templates.
- You have the public IP address of every network that needs access, such as your office and your client’s office.
Create the holding page
Create the page first. Visitors who are not on the list are sent to it, so it must exist before the restriction goes on.
- Go to the Pages list and create a new Page.
- Set Store to the store you are restricting.
- Set Path to
access-restricted. - Set Title to the message visitors see, for example
This site is not open yet. - (Optional) Add
Your IP address is {{ current_request.ip }}to Content Body. A team member who lands on the holding page can then send you the address to add to the list. - Save the page.
The page is now live at /access-restricted on your store. If the store has a Path, such as au, the page is at /au/access-restricted.
Restrict the store to your IP addresses
controllers/theme runs before every storefront page, so a redirect in the before phase stops the page rendering for anyone not on the list.
:::warning The restriction applies to every store that uses this theme. To restrict one store only, give it its own Theme first. :::
- Open the Theme record your store uses.
- On the Theme Templates related list, create a new Theme Template.
- Set Key to
controllers/theme. - Set Content to the following, replacing the two example addresses with your own:
```liquid
{% liquid
before
assign allowed_ips = "203.0.113.10,198.51.100.25" | split: ","
assign visitor_ip = current_request.ip | strip
assign local_path = current_request.local_path
assign holding_path = current_request.store_path | append: "/access-restricted"
assign exempt = false
if local_path == "/access-restricted" or local_path contains "/inbound_webhooks/" or local_path contains "/payment/postback" or local_path contains "/pos/card_capture/" or local_path contains "/embedded_payment"
assign exempt = true
endif
unless allowed_ips contains visitor_ip or exempt
redirect to: holding_path, status: 302
endunless
endbefore
%}
```
Separate the addresses with a comma and no spaces. An address with a space next to it does not match. The `exempt` check lets the holding page itself load. Without it, the holding page redirects to itself and the browser shows a "too many redirects" error. The same check lets through the requests listed under [What the IP restriction covers](#what-the-ip-restriction-covers). `store_path` keeps the redirect on the right store when the store has a **Path**.
- Save the template.
Visit the store from an address on the list and the storefront loads as normal. From any other address, including a phone on mobile data, the browser lands on /access-restricted.
What the IP restriction covers
The restriction applies to storefront pages, including component reloads on those pages. The StoreConnect API and the POS app do not run the theme controller, so API clients and registers are not affected.
Some storefront routes are reached from outside your network even while you test. The exempt condition in the controller lets these through, so test orders and fulfillment keep working:
- Payment postbacks — a payment provider’s servers confirm a payment at
/checkout/payment/postbackor/orders/<reference>/payment/postback. - Shipping and fraud webhooks — Bringg, EasyPost, Easyship, Forter, Ship24, ShipEngine, and Shippit send updates to
/async/inbound_webhooks/<service>. - POS subscription card capture — a customer enters card details for a POS order’s subscriptions at
/pos/card_capture/<reference>. - Embedded payment form — external apps load the payment form for API-created carts at
/embedded_payment.
Remove a line from the condition if your store does not use that route. Payment returns through the visitor’s own browser, such as after a 3D Secure check, need no exemption, because the visitor is already on an allowed address.
The restriction does not remove a store from search results. If the store was public before, search engines keep the pages they already indexed. Turn on stealth mode as well so they drop them.
The restriction matches exact addresses. If a network that needs access does not have a static IP address, the address can change and lock that network out. Ask the people on that network to check the holding page and send you their new address.
Remove the restriction at launch
- Open the Theme record your store uses.
- On the Theme Templates related list, delete the
controllers/themetemplate.
If the template also holds other theme controller logic, such as global variables, delete only the unless … endunless lines that hold the IP check instead. The storefront now loads for every visitor.
Was this article helpful?
Thanks for your feedback! It helps us improve our docs.