Block certain countries from Contact Form 7?

Question

Our brand has the same name as a company in Asia, and we get lots of messages relating to this via Contact Form 7 which messes up our marketing analytics. About 75% of mail is from these customers so I’d love to find a way to prevent this.

We only service the UK, so I’m wondering if there is a way to modify CF7 to block certain countries from using the form? Or if there is a better way of doing it?

[Reddit] Potential ways to limit unwanted CF7 mail caused by brand name confusion?

Our answer

There are several ways you could keep visitors from certain from visiting your Contact Form 7 page. In fact, the approaches below can apply to blocking visitors to any WordPress contact form page. The approaches are:

1. Use a GeoIP blocking plugin

There are several plugins available for WordPress that can help you block visitors based on their geographic location. Some popular options include:

These plugins allow you to set up rules to either redirect or block users from specific countries from accessing your website or certain pages, including the Contact Form 7 page. As an example, the configuration page for plugin IP2Location Redirection looks like this:

So, for visitors in your blacklisted country you can simply redirect your contact form page to your home page, and they’ll never get the opportunity to complete it. Further, you could redirect them to a dedicated explanation page, which details why their location isn’t supported.

Here’s a video rundown of the process:

2. Use Cloudflare or other CDN that supports country blocking

If you’re using Cloudflare as your CDN (Content Delivery Network) or security provider, you can set up country-based blocking rules. This can be done by navigating to the “Firewall” section in your Cloudflare dashboard, and then creating a new Firewall rule that blocks access based on the visitor’s country.

Here’s how to do it:

  1. Log in to the Cloudflare dashboard and select the domain you want to block traffic from.
  2. Click on the “Security” in the sidebar, and then click on “WAF“.
  3. Click on the “Create Rule” button.
  4. In the “If incoming requests match…” section, select “Country” from the dropdown list, leave the operator field at “Equals“, the select the country you wish to block from the “Value” dropdown list. Stopping here would block the entire site from access from your selected country.
  5. Click “And” and select “Full URI” from the first dropdown. Leave the operator field at “Equals“, then enter the full address of your contact form page into the next text field, for example, https://nanopo.st/contact/.
  6. In the “Then” section, select “Block” from the dropdown menu.
  7. Click on the “Deploy” button to save and activate your firewall rule.

3. Custom Code

If you prefer a more hands-on approach, you can add custom code to your site to block users based on their IP address. You can use an API, such as one of the following to determine the user’s country based on their IP:

Here’s a basic example which will block visitors from defined countries to any page which holds the [contact-form-7] shortcode, using any one of these three services:

define( 'MAXMIND_API_KEY', 'your_maxmind_api_key' );
define( 'IP2LOCATION_API_KEY', 'your_ip2location_api_key' );
define( 'GEOLOCATION_METHOD', 'maxmind' ); // Or 'ip2location' or 'cloudflare'

function block_users_by_country() {
    global $post;

    // Check if the current page contains a Contact Form 7 shortcode
    if ( ! is_object( $post ) || 
         ! has_shortcode( $post->post_content, 'contact-form-7' ) 
       ) {
        return;
    }

    $visitor_ip = $_SERVER['REMOTE_ADDR'];
    $country_code = '';

    switch ( GEOLOCATION_METHOD ) {
        case 'maxmind':
            $geoip_endpoint = "https://geoip.maxmind.com/geoip/v2.1/country/";
            $geoip_url = $geoip_endpoint . "{$visitor_ip}?apiKey=" . MAXMIND_API_KEY;
            $response = wp_remote_get( $geoip_url );

            if ( is_wp_error( $response ) ) {
                return;
            }

            $country_data = json_decode( wp_remote_retrieve_body( $response ), true );
            $country_code = $country_data['country']['iso_code'];
            break;

        case 'ip2location':
            $ip2location_endpoint = "https://api.ip2location.com/v2/{$visitor_ip}?key=" . IP2LOCATION_API_KEY . "&package=WS1";
            $response = wp_remote_get( $ip2location_endpoint );

            if ( is_wp_error( $response ) ) {
                return;
            }

            $country_data = json_decode( wp_remote_retrieve_body( $response ), true );
            $country_code = $country_data['country_code'];
            break;

        case 'cloudflare':
            if ( ! isset( $_SERVER["HTTP_CF_IPCOUNTRY"] ) ) {
                return;
            }

            $country_code = $_SERVER["HTTP_CF_IPCOUNTRY"];
            break;

        default:
            return;
    }

    // Replace 'XX' and 'YY' with the 2-letter country codes you want to block
    $blocked_countries = array( 'XX', 'YY' );

    if ( ! in_array( $country_code, $blocked_countries ) ) {
        return;
    }

    // Show a custom message or redirect to another page
    wp_die( 'Sorry, but our services are not available in your country.' );
}

add_action( 'template_redirect', 'block_users_by_country' );

Remember to replace 'your_maxmind_api_key' or 'your_ip2location_api_key' with your actual API key and 'XX', 'YY' with the country codes you want to block.

Improving performance with caching

When dealing with frequent API calls, caching becomes an important mechanism for performance improvement. We can use the WordPress Transients API, to achieve this and to significantly reduce the load time and improve overall performance.

In the given example of blocking users by country, the site retrieves the country code of the visitor’s IP using an API call. When this operation is frequently executed, say for every new visit or page refresh, the overhead of the API call can add up, slowing down the site and consuming more resources.

To alleviate this, we can cache the country code for each visitor, setting a transient for each visitor’s country code, keyed by their IP address, with an expiry time of 24 hours. The code for this looks like this:

$visitor_ip = $_SERVER['REMOTE_ADDR'];
$country_code = get_transient( 'country_code_' . $visitor_ip );

if ( ! $country_code ) {
    switch ( GEOLOCATION_METHOD ) {
        // ... same code as in previous example ...
    }
    // Set the transient if not previously set
    set_transient( 'country_code_' . $visitor_ip, $country_code, 24 * HOUR_IN_SECONDS );
}

In this snippet, get_transient first attempts to fetch the country code from the cache. If it’s not available (which will be the case for the first visit or after 24 hours), the code fetches the country code using the API call, then stores it in the cache with set_transient.

As a result, subsequent requests within the 24-hour window will not trigger a new API call, but instead, quickly retrieve the cached country code. The difference can be between a cached call that takes milliseconds vs and API call that takes seconds.

4. Use Wordfence Country Blocking

An additional method for blocking visitors from specific countries to your WordPress contact form page is to use the Wordfence Country Blocking feature. Wordfence is a well-known security plugin for WordPress that provides robust protection, including country blocking capabilities.

The Wordfence Country Blocking feature allows you to restrict access to your site based on the visitor’s geographical location. You can decide to block certain countries from accessing your entire site or just specific pages, such as the contact form page.

Here is a step-by-step guide on how to set up Wordfence Country Blocking:

  1. Install and activate the Wordfence Security plugin on your WordPress site.
  2. Navigate to Wordfence from your WordPress dashboard and click on ‘Firewall’.
  3. Select the ‘Blocking’ tab and then click on ‘Blocking Options’.
  4. From there, select ‘Country Blocking’.
  5. Choose which pages you want to block access to:
    • ‘Block access to the login form’ is an effective way to stop brute force login attacks from a specific country.
    • ‘Block access to the rest of the site (outside the login form)’ allows you to block access for the selected countries to all parts of your site except the login form.
  6. Select the countries you wish to block.
  7. Configure the advanced country blocking options if necessary. Here you can decide what to do when someone from a blocked country tries to access your site. You can either show a standard “Your access has been temporarily limited” message, or you can redirect the blocked user to a custom page on your site or an external site.

With Wordfence, you also have the ability to bypass the country blocking for specific users or URLs. This can be useful if you have a team member traveling to a blocked country who needs access to your site, or if you want to grant access to a user from a blocked country.

Wordfence is a flexible option for country blocking. While it’s more than just a country blocking plugin, this functionality is well developed and offers a great deal of control over who can access your site or specific pages within it.

Remember to regularly update your Wordfence plugin and the geolocation database to ensure the accuracy and effectiveness of the country blocking feature. This will help you maintain the security and functionality of your website.

With Wordfence, you also have the ability to bypass the country blocking for specific users or URLs. This can be useful if you have a team member traveling to a blocked country who needs access to your site, or if you want to grant access to a user from a blocked country.

Wordfence is a very flexible and reliable option for country blocking. While it’s more than just a country blocking plugin, this functionality is well developed and offers a great deal of control over who can access your site or specific pages within it.


Important notes

  1. These plugins may not work behind a page cache. So, if you’re using a page caching plugin, such as WP Rocket or WP Super Cache, or a CDN, such as Cloudflare or other Bunny.net, make sure to add your contact page to the cache exclusion list for this to work.
  2. Blocking access to your entire site can potentially harm your search engine rankings, as it can prevent Google and other search and aggregation services from crawling your site. Furthermore, if you are using Google Ads on your site, you may face penalties for blocking access to your site.
  3. Remember to regularly update your geolocation database to ensure the accuracy and effectiveness of the country blocking feature.

Leave a Reply

Your email address will not be published. Required fields are marked *