WooCommerce:如何基于地理定位国家拦截特定产品的直接访问
Hey there! I see you’ve already nailed the geolocation-based product hiding for archive, category, and search pages—great work! The direct product page access loophole is a common snag, but we can fix that with a simple addition to your existing code.
The Problem
Your current code hides restricted products from listing pages, but users can still reach them via direct URLs. We need to intercept requests to those single product pages and block access based on the user’s country.
The Fix
We’ll use the template_redirect hook (which fires right before WordPress loads the page template) to add a check for single product pages. Here’s the updated code:
// Existing code: Hide products on archive/search pages add_action( 'woocommerce_product_query', 'bbloomer_hide_product_if_country_new', 9999, 2 ); function bbloomer_hide_product_if_country_new( $q, $query ) { if ( is_admin() ) return; $location = WC_Geolocation::geolocate_ip(); $hide_products = array( 17550, 32 ); $country = $location['country']; if ( $country === "US" ) { $q->set( 'post__not_in', $hide_products ); } } // New code: Block direct access to restricted single product pages add_action( 'template_redirect', 'bbloomer_block_direct_product_access_by_country' ); function bbloomer_block_direct_product_access_by_country() { // Exit if we're not on a single product page or in the admin area if ( ! is_product() || is_admin() ) return; $location = WC_Geolocation::geolocate_ip(); $hide_products = array( 17550, 32 ); $country = $location['country']; $current_product_id = get_the_ID(); // Check if user is from restricted country and accessing a blocked product if ( $country === "US" && in_array( $current_product_id, $hide_products ) ) { // Option 1: Redirect to shop page with an error notice (user-friendly) wc_add_notice( __( 'This product is not available in your country.', 'woocommerce' ), 'error' ); wp_redirect( get_permalink( wc_get_page_id( 'shop' ) ) ); exit; // Option 2: Show 404 error page (makes product seem non-existent) // global $wp_query; // $wp_query->set_404(); // status_header( 404 ); // get_template_part( 404 ); // exit; } }
How It Works
- Hook into
template_redirect: This lets us intercept the request early, before the product page loads. - Check Context: We first confirm we’re on a single product page and not in the admin dashboard.
- Reuse Geolocation Logic: We pull the user’s country using the same
WC_Geolocationmethod as your existing code. - Block Access: If the user is from the restricted country (US) and viewing a blocked product, we either:
- Redirect them to the shop page with a clear error notice (Option 1, recommended for user experience), or
- Trigger a 404 error to make the product appear unavailable entirely (Option 2, uncomment the lines to use this).
Pro Tip to Avoid Duplication
To keep your code clean, define the restricted products as a constant so you don’t have to update the array in two places:
// Define once at the top of your functions.php define( 'RESTRICTED_PRODUCTS', array( 17550, 32 ) ); // Then use RESTRICTED_PRODUCTS in both functions instead of the array
Testing
Make sure to test this with a VPN to simulate being in the US—try accessing the direct product URL to confirm it blocks access as expected.
内容的提问来源于stack exchange,提问作者Hannah James

