Customizations
Ad Inserter uses WordPress action and filter hooks to insert codes into WordPress pages. Each block has many settings so you can insert it practically anywhere on any page. This will work fine for most websites. However, in some cases you may need additional filters or actions not available in the plugin. For this purpose Ad Inserter offers additional actions, filters and hooks to extend the plugin functionality.
Filter Hooks
Custom block insertion checks
ai_block_insertion_check ($enabled, $block, $server_side_check)
This filter hook is called just before the block is to be inserted – all the settings were already checked. This is a place where you can prevent insertion. When the function returns false
the block will not be inserted. See below for details.
$enabled
is the default return value (normally true).
$block
is the block number – it is set to 0 when the call is a client-side check for all blocks – in such a case an array of enabled blocks should be returned. Alternatively, the array can contain *
which means all blocks are enabled and optionally negative block numbers of disabled blocks, for example array ('*', - 5, -10)
.
$server_side_check
is true when the check is done server-side (when the page is created). The function should return null
to be called client-side once again – this is a typical case where the website uses caching and checks need to be done client-side (in the browser). For single block checks (block number from 1 to 96) the function should return true if the block is enabled.
The hook function can set a global variable $ai_block_insertion_check_comments
with some debugging data which is shown when the Label blocks debugging function is used.
Example 1 – check IP address against the blacklisted IP addresses in a file:
// Example for blacklisted IP addresses in a file located at /wp-content/uploads/blocked-ip-addresses.txt
// This approach requires Ad Inserter Pro
function ai_block_insertion_check_ip_addresses ($enabled, $block, $server_side_check) {
global $ai_wp_data, $ai_block_insertion_check_comments, $ip_address_found;
// Return null to signal client-side checks (in the case pages are cached)
if ($server_side_check) {
return null;
}
// Check the address and store it to $ip_address_found
if (!isset ($ip_address_found)) {
require_once AD_INSERTER_PLUGIN_DIR.'includes/geo/Ip2Country.php';
// Load the file with IP addresses and prepare a string with comma separated addresses
$upload_dir = wp_upload_dir ();
$blocked_ip_addresses = str_replace (array ("\n", "\r"), array (',', ''), file_get_contents ($upload_dir ['basedir'] . '/blocked-ip-addresses.txt'));
// Use function check_ip_address_list () of Ad Inserter Pro to check the IP addresses (wildcards are possible as in IP address list)
$ip_address_found = check_ip_address_list ($blocked_ip_addresses, true);
}
// Debugging info
if ($ai_wp_data [AI_WP_DEBUGGING] != 0) {
if ($ip_address_found) $ai_block_insertion_check_comments = 'BLOCKED IP ADDRESS: ' . get_client_ip_address ();
}
// For block 0 return an array of enabled blocks
if ($block == 0) {
// If IP address is blocked then return empty array
if ($ip_address_found) return array ();
// Otherwise all blocks are enabled
return array ('*');
}
return !$ip_address_found;
}
add_filter ('ai_block_insertion_check', 'ai_block_insertion_check_ip_addresses', 10, 3);
Example 2 – check the client with ipqualityscore.com – make sure you use your key:
// Example for https://www.ipqualityscore.com/
function ai_block_insertion_check_ipqualityscore ($enabled, $block, $server_side_check) {
global $ai_wp_data, $ai_block_insertion_check_comments, $ipqualityscore_data;
// Return null to signal client-side checks (in case pages are cached)
if ($server_side_check) {
return null;
}
// Get the data and store it to $ipqualityscore_data
if (!isset ($ipqualityscore_data)) {
// Your API Key
$key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// Retrieve the user's IP address. You could also pull this from another source such as a database.
if (file_exists (AD_INSERTER_PLUGIN_DIR.'includes/geo/Ip2Country.php')) {
// This approach requires Ad Inserter Pro
require_once AD_INSERTER_PLUGIN_DIR.'includes/geo/Ip2Country.php';
$ip = get_client_ip_address ();
} else {
// This approach works with Ad Inserter
$ip = isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR'];
}
// Retrieve additional (optional) data points which help us enhance fraud scores.
if (!$server_side_check && isset ($_GET ['http_user_agent']) && isset ($_GET ['http_accept_language'])) {
// Ajax request for client-side checks
$user_agent = urldecode ($_GET ['http_user_agent']);
$user_language = urldecode ($_GET ['http_accept_language']);
} else {
// Server-side or server-sice W3TC check
$user_agent = $_SERVER ['HTTP_USER_AGENT'];
$user_language = $_SERVER ['HTTP_ACCEPT_LANGUAGE'];
}
// Set the strictness for this query. (0 (least strict) - 3 (most strict))
$strictness = 1;
// You may want to allow public access points like coffee shops, schools, corporations, etc...
$allow_public_access_points = 'true';
// Reduce scoring penalties for mixed quality IP addresses shared by good and bad users.
$lighter_penalties = 'false';
// Create parameters array.
$parameters = array(
'user_agent' => $user_agent,
'user_language' => $user_language,
'strictness' => $strictness,
'allow_public_access_points' => $allow_public_access_points,
'lighter_penalties' => $lighter_penalties
);
// User & Transaction Scoring
// Score additional information from a user, order, or transaction for risk analysis
// Please see the documentation and example code to include this feature in your scoring:
// https://www.ipqualityscore.com/documentation/proxy-detection/transaction-scoring
// This feature requires a Premium plan or greater
// Format Parameters
$formatted_parameters = http_build_query ($parameters);
// Create API URL
$url = sprintf ('https://www.ipqualityscore.com/api/json/ip/%s/%s?%s', $key, $ip, $formatted_parameters);
// Fetch The Result
$timeout = 5;
$curl = curl_init();
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$json = curl_exec ($curl);
curl_close ($curl);
// Decode the result into an array.
$ipqualityscore_data = json_decode ($json, true);
}
// For block 0 return array of enabled blocks
if ($block == 0) {
// Check to see if our query was successful.
if (isset ($ipqualityscore_data ['success']) && $ipqualityscore_data ['success']) {
// Debugging info
if ($ai_wp_data [AI_WP_DEBUGGING] != 0) {
$ai_block_insertion_check_comments = $ipqualityscore_data;
}
// Example 1: We'd like to block all proxies
if ($ipqualityscore_data ['proxy'] === true){
$enabled = false;
}
// Example 2: We'd like to block all proxies, but allow legitimate crawlers like Google on our site
if ($ipqualityscore_data ['proxy'] === true && $ipqualityscore_data ['is_crawler'] === false){
$enabled = false;
}
// Example 3: We'd like to block only visitors with a fraud score, over 80, but allow crawlers such as Google
if ($ipqualityscore_data ['fraud_score'] >= 80 && $ipqualityscore_data ['is_crawler'] === false) {
$enabled = false;
}
// Example 4: We'd like to block only visitors which are a proxy with a fraud score over 80, but allow crawlers such as Google
if ($ipqualityscore_data ['proxy'] === true && $ipqualityscore_data ['fraud_score'] >= 80 && $ipqualityscore_data ['is_crawler'] === false) {
$enabled = false;
}
// Example 5: We'd like to block only visitors which are using tor
if ($ipqualityscore_data ['tor'] === true){
$enabled = false;
}
}
// If not enabled then return empty array
if (!$enabled) return array ();
// All blocks are enabled
return array ('*');
}
// Return individual block status
return $enabled;
}
add_filter ('ai_block_insertion_check', 'ai_block_insertion_check_ipqualityscore', 10, 3);
PRO Custom gelolocation services
ai_ip_to_country ($default, $ip, $details)
This filter hook is called before IP address to country lookup. You can use it for custom geolocation services. $default
is the default return value, $ip
is the IP address of the client, $details
is true
when country subdivision data is required (ignore it if your database contains only country data). The function should return uppercase two-character country ISO code. When the function returns false
the configured Ad Inserter Pro lookup will be used. Code example:
add_filter ('ai_ip_to_country', 'custom_ip_to_country', 10, 3);
function custom_ip_to_country ($default, $ip, $details) {
// $default: default return value (false, means not found and configured Ad Inserter Pro lookup will be used)
// $ip: IP address of the client
// $details: true when country subdivision data is required (ignore it if your database contains only country data)
// DB lookup
return 'XX'; // Uppercase country ISO code
// for country subdivisions
// return array ($isoCode, $subdivision, $city); // Complete data
// when not found
// return false; // false means not found and configured Ad Inserter Pro lookup will be used
}
Code example to check Kosovo IP ranges:
add_filter ('ai_ip_to_country', 'kosovo_ip_to_country', 10, 3);
function kosovo_ip_to_country ($default, $ip, $details) {
$kosovo_ipv4_ranges = array (
"46.99.0.0-46.99.255.255",
"80.80.160.0-80.80.175.255",
"91.187.96.0-91.187.127.255",
"37.26.64.0-37.26.71.255",
"185.248.172.0-185.248.175.255",
"185.254.116.0-185.254.119.255",
"147.78.160.0-147.78.163.255",
"91.217.14.0-91.217.15.255",
"46.19.224.0-46.19.231.255",
"82.114.64.0-82.114.95.255",
"178.132.216.0-178.132.223.255",
"185.67.176.0-185.67.179.255",
"185.190.132.0-185.190.135.255",
"193.0.254.0-193.0.254.255",
"178.175.0.0-178.175.127.255",
"185.47.188.0-185.47.191.255",
"213.163.96.0-213.163.127.255",
"94.100.48.0-94.100.63.255",
"77.247.248.0-77.247.255.255",
"185.177.28.0-185.177.31.255",
"185.188.216.0-185.188.219.255",
"185.24.32.0-185.24.35.255",
"185.114.112.0-185.114.115.255",
"185.205.168.0-185.205.171.255",
"185.222.138.0-185.222.138.255",
"185.244.24.0-185.244.27.255",
"194.169.164.0-194.169.167.255",
"147.78.160.0-147.78.163.255",
"45.84.116.0-45.84.119.255",
"194.5.235.0-194.5.235.255",
"185.190.38.0-185.190.38.255",
"37.35.64.0-37.35.71.255",
"84.22.32.0-84.22.63.255",
"185.173.204.0-185.173.207.255",
"84.22.32.0-84.22.63.255",
"185.82.108.0-185.82.111.255",
"185.196.180.0-185.196.183.255",
"194.5.235.0-194.5.235.255",
"194.5.252.0-194.5.252.255",
"194.6.234.0-194.6.234.255",
"194.6.247.0-194.6.247.255",
"185.188.248.0-185.188.251.255",
"91.239.145.0-91.239.145.255",
"5.206.232.0-5.206.239.255",
"87.238.208.0-87.238.215.255",
"185.171.60.0-185.171.63.255",
"185.174.208.0-185.174.211.255",
"185.179.28.0-185.179.31.255",
"185.186.80.0-185.186.83.255",
"185.191.164.0-185.191.167.255"
);
foreach ($kosovo_ipv4_ranges as $kosovo_ipv4_range) {
$range_addresses = explode ('-', $kosovo_ipv4_range);
$ip_address = ip2long ($ip);
$low_address = ip2long ($range_addresses [0]);
$high_address = ip2long ($range_addresses [1]);
if (is_int ($ip_address) && is_int ($low_address) && is_int ($high_address)) {
if ($ip_address >= $low_address && $ip_address <= $high_address) {
return 'XK';
}
}
}
// Not found
return false; // false means not found and configured Ad Inserter Pro lookup will be used
}
PRO Custom ad blocking detection scripts path
ai_adb_scripts_path ($default)
When ad blocking detection is set to Advanced, Ad Inserter Pro moves scripts for ad blocking detection to a folder with random name. By default the scripts are moved into /wp-content/uploads
.
This filter hook is called on init
action hook just before the scripts used for ad blocking detection are moved. With this filter you can define a custom folder according to your needs. In any case Ad Inserter Pro will either in the default or in the specified folder create subfolders ad-inserter/random-name/
where the scripts will be placed.
The custom folder returned by this filter hook must already exist.
You need to add filter hook before it is used in the init
action, for example on action after_setup_theme
. Check WP Plugin API Action Reference for the order of WP action hooks.
function adb_scripts_path ($path) {
return '/wp-content/static';
}
add_filter ('ai_adb_scripts_path', 'adb_scripts_path', 10, 1);
Custom ad labels
ai_block_ad_label ($label_code, $block_number)
This filter hook is called before the ad label for the block is returned. With this filter you can define a custom label or translate it with your translation solutuion. $label_code
is the original (configured) ad label value (text or HTML code), $block_number
is the number of the block for which the label is returned.
function block_ad_label ($label_code, $block_number) {
if ($block_number == 1) return 'Block 1';
return $label_code;
}
add_filter ('ai_block_ad_label', 'block_ad_label', 10, 2);
Javascript actions
PRO Manual loading of blocks
This function loads blocks when they are set to be loaded manually. The block number parameter is optional, if it is not provided all blocks enabled for manual loading (and not loaded yet) will be loaded. Of course, the code for the ads needs to support asynchronous loading (loading after the page is created).
PRO Action when a block is clicked
ai_click_action (block, block_name, code_version, code_version_name)
When the plugin detects a click on a block with enabled tracking, it calls Javascript function ai_click_action
with block data as parameters.
PRO Action when a block is closed
ai_close_button_action (block)
When a block is closed, the plugin calls Javascript function ai_close_button_action
with block number as parameter.
To close all blocks when one block is closed you can use the following approach:
function ai_close_button_action (block) {
document.querySelectorAll ('.ai-close .ai-close-button').forEach ((block_to_close, index) => {
ai_close_block (block_to_close);
});
}
PRO Action for external tracking
ai_external_tracking_event (event_data, category, action, label, non_interaction)
Before the plugin generates event for external tracking it calls Javascript function ai_external_tracking_event
with various event data as parameters. category, action and label are defined on the Tracking settings tab, non_interaction is a parameter for the Google analytics events and event_data is defined as object:
var event_data = {'event': event, 'block': block, 'block_name': block_name, 'block_counter': block_counter, 'version': version, 'version_name': version_name};
You can use this function to define custom actions for external tracking, for example, when you are using some unsupported web analytics. When the function ai_external_tracking_event
returns 0 no further actions are performed. Otherwise the tracking event is sent also to Google Analytics, GTM, Piwik web analytics and other supported external tracking services.