';
}
/**
* Advanced section callback
*/
public static function advanced_section_callback()
{
echo '
' . esc_html__('Advanced configuration options. Only change these if you know what you\'re doing.', 'airefs-ai-search-analytics-tracking') . '
';
}
/**
* Access token field
*/
public static function access_token_field()
{
$options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
$value = isset($options['access_token']) ? $options['access_token'] : '';
echo '';
echo '';
echo '
' . sprintf(
esc_html__('Enter your Airefs Access Token. You can find this in your Airefs Dashboard.', 'airefs-ai-search-analytics-tracking'),
'',
''
) . '
';
}
/**
* Tracking enabled field
*/
public static function tracking_enabled_field()
{
$options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
$value = isset($options['tracking_enabled']) ? $options['tracking_enabled'] : true;
echo '';
echo '
' . esc_html__('When enabled, the plugin will track clicks from AI search results to your website.', 'airefs-ai-search-analytics-tracking') . '
';
}
/**
* Cache vary field
*/
public static function cache_vary_field()
{
$options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
$value = isset($options['enable_cache_vary']) ? $options['enable_cache_vary'] : false;
echo '';
echo '
' . esc_html__('When enabled, adds User-Agent to cache vary headers for better AI bot detection. This may impact site performance by reducing cache effectiveness.', 'airefs-ai-search-analytics-tracking') . '
' . esc_html__('Comma-separated query names that identify different content, for example countries. WordPress p and page_id are always preserved when valid. Up to 16 names, using letters, numbers, underscores or hyphens and starting with a letter. Names are case-sensitive. Never add personal data; credential, session and tracking names are blocked. New settings apply only to newly captured events.', 'airefs-ai-search-analytics-tracking') . '
';
}
/**
* API endpoint field
*/
public static function api_endpoint_field()
{
$options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
$value = isset($options['api_endpoint']) ? $options['api_endpoint'] : 'https://api.getairefs.com';
echo '';
echo '' . esc_html__('API Endpoint Configuration', 'airefs-ai-search-analytics-tracking') . '';
echo '';
echo '
' . esc_html__('The Airefs API endpoint. Only change this if instructed by Airefs support.', 'airefs-ai-search-analytics-tracking') . '
';
echo '';
}
/**
* Settings page
*/
public static function settings_page()
{
// Check user capabilities
if (!current_user_can('manage_options')) {
return;
}
// Get options for connection test
$options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
$has_access_token = !empty($options['access_token']);
?>
airefs.com'
); ?>
0
? __('Events are queued for background delivery.', 'airefs-ai-search-analytics-tracking')
: ($health['last_success'] > 0
? __('The last delivery was confirmed; no events are waiting.', 'airefs-ai-search-analytics-tracking')
: __('Waiting for the first confirmed delivery.', 'airefs-ai-search-analytics-tracking')))));
?>
0): ?>
0 && $health['last_rejected'] >= time() - 600) {
return __('Some new events could not be saved. Check queue storage and delivery errors; already saved events are retained.', 'airefs-ai-search-analytics-tracking');
}
if ($health['blocked'] > 0) {
return __('Some saved events need attention before they can be delivered.', 'airefs-ai-search-analytics-tracking');
}
if ($health['error'] !== '' || $health['scheduler_error'] !== '') {
return __('Background delivery needs attention. Saved events are retained.', 'airefs-ai-search-analytics-tracking');
}
if ($health['capacity_bytes'] > 0 && $health['bytes'] >= $health['capacity_bytes'] * 0.8) {
return __('Queue storage is nearly full. Check delivery before new events can no longer be saved.', 'airefs-ai-search-analytics-tracking');
}
if ($health['count'] > 0 && $health['oldest'] > 0 && $health['oldest'] < time() - 600) {
return __('Delivery is delayed: events have been waiting for more than ten minutes.', 'airefs-ai-search-analytics-tracking');
}
return '';
}
/**
* Sanitize settings
*/
public static function sanitize_settings($input)
{
$existing = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
$sanitized = array();
foreach (array('plugin_version', 'htaccess_cleanup_complete') as $key) {
if (isset($existing[$key])) {
$sanitized[$key] = $existing[$key];
}
}
// Sanitize access token
if (isset($input['access_token'])) {
$sanitized['access_token'] = sanitize_text_field($input['access_token']);
}
// Sanitize tracking enabled
$sanitized['tracking_enabled'] = isset($input['tracking_enabled']) ? (bool) $input['tracking_enabled'] : false;
// Sanitize cache vary enabled
$sanitized['enable_cache_vary'] = isset($input['enable_cache_vary']) ? (bool) $input['enable_cache_vary'] : false;
$sanitized['url_query_allowlist'] = airefs_tracking_query_allowlist(isset($existing['url_query_allowlist']) ? $existing['url_query_allowlist'] : array());
if (isset($input['url_query_allowlist'])) {
$raw = $input['url_query_allowlist'];
$names = is_string($raw) ? (trim($raw) === '' ? array() : explode(',', $raw)) : $raw;
$valid = is_array($names);
$allowed = array();
if ($valid) {
foreach ($names as $name) {
if (!is_string($name) || !airefs_tracking_valid_query_name(trim($name))) {
$valid = false;
break;
}
$allowed[] = trim($name);
}
}
$allowed = array_values(array_unique(array_diff($allowed, array('p', 'page_id'))));
if ($valid && count($allowed) <= 16) {
$sanitized['url_query_allowlist'] = airefs_tracking_query_allowlist($allowed);
} else {
add_settings_error(AIREFS_TRACKING_OPTIONS_NAME, 'invalid_url_query_allowlist', __('Content query parameters were not changed. Enter at most 16 names starting with a letter, with up to 64 letters, numbers, underscores or hyphens each. Credential, session and tracking names are not allowed.', 'airefs-ai-search-analytics-tracking'));
}
}
// Sanitize API endpoint
if (isset($input['api_endpoint'])) {
$endpoint = esc_url_raw($input['api_endpoint']);
$sanitized['api_endpoint'] = airefs_tracking_origin($endpoint) ? rtrim($endpoint, '/') : 'https://api.getairefs.com';
}
return $sanitized;
}
/**
* Admin notices
*/
public static function admin_notices()
{
$options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array());
if (current_user_can('manage_options')) {
$health = AirefsTrackingQueue::health();
$warning = self::delivery_warning($health);
if ($warning !== '') {
$notice_class = $health['storage_ready'] ? 'notice-warning' : 'notice-error';
echo '
';
}
if (isset($options['htaccess_cleanup_complete']) && !$options['htaccess_cleanup_complete']) {
echo '
' . esc_html__('Airefs could not remove its legacy .htaccess block. Make the file writable or remove only the block marked “Airefs AI Bot Exclusion”. Cleanup will retry automatically.', 'airefs-ai-search-analytics-tracking') . '
';
delete_transient('airefs_cleanup_completed');
}
}
// Show notice if access token is not set
if (empty($options['access_token']) && current_user_can('manage_options')) {
$settings_url = admin_url('options-general.php?page=' . self::SETTINGS_PAGE);
?>
',
''
); ?>
__('No Access Token configured.', 'airefs-ai-search-analytics-tracking')
));
}
$api_endpoint = isset($options['api_endpoint']) ? $options['api_endpoint'] : 'https://api.getairefs.com';
// Test API connection
$response = wp_remote_get($api_endpoint . '/health', array(
'headers' => array(
'Authorization' => 'Bearer ' . $options['access_token'],
'User-Agent' => AIREFS_TRACKING_UA,
),
'timeout' => 10,
'redirection' => 0,
'limit_response_size' => 4096,
));
if (is_wp_error($response)) {
wp_send_json_error(array(
// translators: %s is the error message
'message' => sprintf(__('Connection failed: %s', 'airefs-ai-search-analytics-tracking'), $response->get_error_message())
));
}
$status_code = wp_remote_retrieve_response_code($response);
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($status_code === 200 && is_array($body) && isset($body['delivery_protocol'], $body['site_id']) && $body['delivery_protocol'] === 1 && is_string($body['site_id']) && $body['site_id'] !== '') {
$health = AirefsTrackingQueue::health();
if (!$health['storage_ready']) {
wp_send_json_error(array(
'api_connected' => true,
'storage_ready' => false,
'message' => __('API connected. Tracking is not ready: local storage setup failed. Use Retry storage setup under Background delivery after your host resolves the database issue.', 'airefs-ai-search-analytics-tracking')
));
}
wp_send_json_success(array(
'api_connected' => true,
'storage_ready' => true,
'message' => empty($options['tracking_enabled'])
? __('API connected. Local storage is ready, but tracking is paused.', 'airefs-ai-search-analytics-tracking')
: __('API connected. Local storage is ready. Check Background delivery for confirmed event delivery.', 'airefs-ai-search-analytics-tracking')
));
} elseif ($status_code === 200) {
wp_send_json_error(array(
'message' => __('The endpoint responded but does not support confirmed delivery. Saved events will wait until the endpoint is updated.', 'airefs-ai-search-analytics-tracking')
));
} else {
wp_send_json_error(array(
// translators: %d is the HTTP status code
'message' => sprintf(__('Connection failed with status code: %d', 'airefs-ai-search-analytics-tracking'), $status_code)
));
}
}
// Initialize admin functionality
AirefsTrackingAdmin::init();
// Register AJAX handlers
add_action('wp_ajax_airefs_test_connection', 'airefs_test_connection_handler');
function airefs_retry_delivery_handler()
{
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Insufficient permissions.', 'airefs-ai-search-analytics-tracking'), '', array('response' => 403));
}
check_admin_referer('airefs_retry_delivery');
$result = AirefsTrackingQueue::retry_now();
$status = $result === true ? 'scheduled' : 'failed';
wp_safe_redirect(add_query_arg('airefs_delivery', $status, admin_url('options-general.php?page=' . AirefsTrackingAdmin::SETTINGS_PAGE)));
exit;
}
add_action('admin_post_airefs_retry_delivery', 'airefs_retry_delivery_handler');
function airefs_retry_setup_handler()
{
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Insufficient permissions.', 'airefs-ai-search-analytics-tracking'), '', array('response' => 403));
}
check_admin_referer('airefs_retry_setup');
$ready = AirefsTrackingQueue::retry_setup();
wp_safe_redirect(add_query_arg('airefs_setup', $ready ? 'ready' : 'failed', admin_url('options-general.php?page=' . AirefsTrackingAdmin::SETTINGS_PAGE)));
exit;
}
add_action('admin_post_airefs_retry_setup', 'airefs_retry_setup_handler');