Skip to content
  • There are no suggestions because the search field is empty.

How to Block or Segment Visitors by IP Address in Your Experiments

🚫 Control content visibility by filtering visitor access using IP-based targeting with JavaScript and Convert Experiences

🚀 IN THIS ARTICLE YOU WILL:

In some scenarios, you may need to restrict or customize content for visitors based on their IP addresses. This article shows how to implement IP-based visitor filtering in Convert Experiences using a modern approach that properly integrates with Convert's experiment lifecycle.

⚙️ Setting Up IP-Based Filtering

1. Adding the JavaScript Code

Insert the following JavaScript code into the Global JavaScript section of your project:

// Step 1: Fetch the IP and wait for it
function getVisitorIP() {
  return new Promise((resolve, reject) => {
    fetch('https://ipapi.co/json/')
      .then(response => response.json())
      .then(data => {
        resolve(data.ip);
      })
      .catch(error => {
        console.error('Error fetching IP:', error);
        reject(error);
      });
  });
}

// Configuration for IP lists
const config = {
  mode: 'blacklist', // or 'whitelist'
  ipList: [
    '123.456.789.012',         // Single IP
    '192.168.1.0/24',          // CIDR notation
    '10.0.0.1-10.0.0.255'      // Range notation
  ],
  showExperiences: false       // Flag that will be set based on IP check
};

// Step 2 & 3: Check if IP is within Allow/Disallow List and set flag
function checkIPAccess(ip) {
  // Check if IP matches any entry in the list
  const ipMatch = config.ipList.some(entry => {
    // Check if entry is a single IP
    if (!entry.includes('/') && !entry.includes('-')) {
      return ip === entry;
    }
    // Check if entry is in CIDR notation
    else if (entry.includes('/')) {
      return isIPInCIDR(ip, entry);
    }
    // Check if entry is in range notation
    else if (entry.includes('-')) {
      const [start, end] = entry.split('-');
      return isIPInRange(ip, start, end);
    }
    return false;
  });

  // Set the flag based on mode and whether IP matched
  if (config.mode === 'whitelist') {
    config.showExperiences = ipMatch;
  } else { // blacklist mode
    config.showExperiences = !ipMatch;
  }

  return config.showExperiences;
}

// Helper function to check if IP is within a range
function isIPInRange(ip, rangeStart, rangeEnd) {
  const ipNum = ipToNumber(ip);
  const startNum = ipToNumber(rangeStart);
  const endNum = ipToNumber(rangeEnd);

  return ipNum >= startNum && ipNum <= endNum;
}

// Helper function to check if IP is within a CIDR range
function isIPInCIDR(ip, cidr) {
  const [subnet, bits] = cidr.split('/');
  const ipNum = ipToNumber(ip);
  const subnetNum = ipToNumber(subnet);
  const mask = -1 << (32 - parseInt(bits));

  return (ipNum & mask) === (subnetNum & mask);
}

// Helper function to convert IP to number for comparison
function ipToNumber(ip) {
  return ip.split('.')
    .map((octet, index) => parseInt(octet) * Math.pow(256, 3 - index))
    .reduce((sum, num) => sum + num, 0);
}

// Initialize and handle experiment execution
function initializeIPBasedExperiments() {
  let visitorIP;

  // Fetch the IP first
  getVisitorIP().then(ip => {
    visitorIP = ip;
    const shouldShowExperiments = checkIPAccess(ip);
    console.log('IP check result:', shouldShowExperiments ? 'Allow' : 'Block');

    // Wait for Convert to complete its initial evaluation
    document.addEventListener('convert:executed', function() {
      console.log('Initial experiment evaluation completed');

      // Based on our IP check, decide if we need to re-run experiments
      if (!shouldShowExperiments) {
        console.log('Re-running experiments with IP-based restrictions');
        window._conv_q = window._conv_q || [];
        window._conv_q.push({what: 'run'});
      }
    },{ once: true }); // Only trigger this once for the initial execution
  }).catch(error => {
    console.error('Failed to initialize IP-based experiments:', error);
    // Fallback behavior in case of error
    config.showExperiences = false; // Default to showing experiences if IP check fails
  });
}

// Start the process
initializeIPBasedExperiments();

2. Configuring IP Lists

You can configure the script by modifying the config object:

  • Set mode to either 'blacklist' (block specified IPs) or 'whitelist' (allow only specified IPs)

  • Add IP addresses to the ipList array using any of these formats:

    • Single IP: '192.168.1.1'

    • CIDR notation: '192.168.1.0/24'

    • IP Range: '10.0.0.1-10.0.0.255'

3. Integrating with Experiments

With this code in place, you do not need additional JavaScript conditions in your experiment audiences. The script will:

  • Fetch the visitor’s IP address

  • Check if it matches your configured IP rules

  • Let Convert run its initial evaluation

  • Based on the IP check, potentially re-run experiments with the appropriate restrictions

✅ This approach ensures that your IP-based rules are applied consistently across all experiments without falling into evaluation loops.

🛠️ Debugging Tips

To verify the functionality:

  • Open your browser’s developer console

  • Check the logs which will show:

    • The result of the IP check (Allow or Block)

    • When the initial experiment evaluation completes

    • If experiments are being re-run due to IP restrictions

  • You can also type config.showExperiences in the console to see the current state of the IP-based flag.