Manage Product Data Once, Show Test Products Only in Staging
With automatic test product filtering, you can manage product data in one place while hiding test products in production and showing them only in staging. Runtime hostname detection simplifies deployment to a single build.

One Deploy, Two Visibility Rules: Using Product Flags to Control What Shows Where
Automatic test product filtering is an operational safeguard designed to reduce exposure incidents in production. This is not about security — it is not protecting sensitive data or controlling access. The focus is purely on keeping test products off production screens. If you need to hide sensitive data, that calls for a separate measure like server-side blocking.
This pattern is especially practical for teams running custom-built ecommerce platforms, where the product catalog is large and production and staging environments run simultaneously. If you manage your own product data pipeline rather than relying on a hosted solution like Shopify, this one is for you.
What Happens When Test Products Leak Into Production
Test products are necessary. The following scenarios need to be verified under conditions nearly identical to real sales.
- Coupon and promotion logic (discounts, stacking rules, minimum purchase amounts)
- Pricing policy changes (option pricing, limited-time prices, rounding rules)
- Payment and refund flows (payment gateway responses, failure cases, receipts)
- Inventory and display states (out-of-stock labels, restock notifications, etc.)
The problem occurs when these test products show up in production. Picture this: a $0.01 test product created for payment testing lands on a promotional page. Customers place real orders thinking it is a legitimate deal, and your support team spends the morning investigating and processing refunds. One product is containable. But once test products spread into category filters or recommendation sections, the blast radius grows fast.
The common thread in these incidents is simple: someone forgot to manually hide or delete the test product. Any process that relies on someone remembering to do something will eventually fail, so it is safer to let the system handle it automatically.
Goal: One Dataset, Environment-Based Visibility
The goal of this article is straightforward.
- Manage product data once (no separate databases for production and staging).
- Automatically hide test products in production.
- Show test products in staging and local environments.
The core principle is separating “product management” from “product visibility.” Data stays in one place, while visibility rules branch automatically based on the environment.
Implementation Concept: Product Flag + Runtime Hostname Detection
The implementation consists of two components.
1) Identify Test Products With a Flag
Add a field to the product data that indicates whether it is a test product. In this example, we use isTestProduct.
- Sales product: isTestProduct = “false”
- Test product: isTestProduct = “true”
2) Branch Visibility Using Runtime Hostname Detection
Instead of splitting environments at build time with environment variables, read the hostname at runtime. Check window.location.hostname: if the hostname matches a staging or local environment (like stg or localhost), show test products. For all other hostnames (production domains), hide them.
This approach controls visibility on the frontend only, so someone with a direct URL could still access a test product. However, the focus is on structurally preventing large-scale exposure incidents caused by operational mistakes.
Why Hostname: Comparing Approaches
There are several ways to implement environment-based filtering. Here is how they compare.
| Approach | Deploys | Data Duplication | Domain Scalability | Frontend Only? | Incident Prevention |
|---|---|---|---|---|---|
| Per-environment builds | Multiple | None | Good | Yes | Medium |
| Server-side filtering | 1 | None | Good | No | High |
| Runtime hostname (this article) | 1 | None | Very good | Yes | High |
Per-environment builds require separate builds for production and staging. As the service scales, managing the build pipeline becomes a burden. Server-side filtering offers the strongest protection, but it requires API changes and cannot be adopted by the frontend team alone. If backend resources are not immediately available, the initiative stalls before it starts.
The hostname approach sits at a practical midpoint between the two. It works across multiple CDNs, load balancers, and subdomains because it applies policies based on the accessed hostname. It also keeps deployment to a single build. Of course, if you need security-level hiding, server-side filtering is the right choice. The hostname approach is best understood as a “quick-to-adopt operational safeguard on the frontend.”
Example Code: Filtering Results
Below is code showing how filtering works in a production environment (when the hostname is not stg or localhost).
// Mock product data
const data = {
list: [
{ id: 1, name: "Real Product A", isTestProduct: "false", price: 49.99 },
{ id: 2, name: "Test Discount Coupon QA", isTestProduct: "true", price: 0.01 },
{ id: 3, name: "Bestseller Product", isTestProduct: "false", price: 129.00 },
{ id: 999, name: "Internal Super-Discount Test", isTestProduct: "true", price: 0.01 }
]
};
<p class="font-claude-response-body break-words whitespace-pre-wrap leading-[1.7]">// Production environment (not stg/local)
const filtered = data.list.filter(item => item.isTestProduct !== 'true');
// Result: only Product A and Bestseller remain (2 test products auto-hidden)
Before filtering (original list: 4 items)
- id=1 / Real Product A / isTestProduct=false / $49.99
- id=2 / Test Discount Coupon QA / isTestProduct=true / $0.01
- id=3 / Bestseller Product / isTestProduct=false / $129.00
- id=999 / Internal Super-Discount Test / isTestProduct=true / $0.01
After filtering in production (visible list: 2 items)
- id=1 / Real Product A / $49.99
- id=3 / Bestseller Product / $129.00
In production, only sales products remain, and test products are automatically hidden. Adding hostname detection on top of this looks like the following.
const testVisibleHosts = ["stg.example.com", "localhost"];
const isTestVisibleEnv = testVisibleHosts.includes(window.location.hostname);
<p class="font-claude-response-body break-words whitespace-pre-wrap leading-[1.7]">const visibleList = isTestVisibleEnv
? data.list
: data.list.filter(item => item.isTestProduct !== "true");
Even as production domains grow, the default behavior is “hide.” Only the environments that need test products are explicitly allowlisted.
Operations Checklist: Easy-to-Miss Areas Beyond the Product List
Automatic test product filtering does not end with the product list page. Here are the areas that are commonly overlooked in production.
1. Search and Recommendation Sections
On-site search results and recommendation or related-product sections often use separate APIs. Since they fetch data through different paths than the main product list, verify that the same hiding policy is applied to search indexes and recommendation logic. It is also worth checking whether test products are excluded from search engine indexing via robots rules or noindex tags.
2. Cached Pages
If category pages or promotional landing pages are served from a CDN or server cache, test products may remain visible until the cache refreshes. Review cache TTL and purge policies alongside the filtering logic.
3. Consistency Across Product Registration Paths
Confirm that the test product flag is consistently applied across all registration paths: manual entry, product duplication, and bulk uploads. For example, check whether the isTestProduct value resets when duplicating a product in the admin panel, or whether the field mapping is missing in bulk Excel uploads.
4. External Sales Channels
If you syndicate product feeds to external channels like Amazon, Google Shopping, or marketplace platforms, verify that the feed generation logic also excludes test products. Exposure on external channels is harder to remediate than on your own site.
The key takeaway from this checklist: trace every path a test product can reach. The filtering logic itself is simple — but if you miss a path, that is exactly where the incident happens.
Conclusion
Automatic test product filtering is a practical way to reduce production exposure incidents in ecommerce services with large product catalogs. Manage product data in one place, use runtime hostname detection to split environments, and test products stay visible only where they should be — in staging. Just make sure your team understands that this is an operational safeguard, not a security measure.