diff --git a/anytrack-for-woocommerce/trunk/anytrack-for-woocommerce.php b/anytrack-for-woocommerce/trunk/anytrack-for-woocommerce.php index a85a3f2..d9266d1 100755 --- a/anytrack-for-woocommerce/trunk/anytrack-for-woocommerce.php +++ b/anytrack-for-woocommerce/trunk/anytrack-for-woocommerce.php @@ -2,10 +2,10 @@ /* Plugin Name: AnyTrack for WooCommerce Description: Connect with Google, Facebook, Bing, Taboola and Outbrain and sync all your ad campaigns directly from WooCommerce. -Version: 1.5.7 +Version: 1.5.8 Author: AnyTrack Ltd. Author URI: https://anytrack.io -Stable tag: 1.5.7 +Stable tag: 1.5.8 */ //error_reporting(E_ALL); diff --git a/anytrack-for-woocommerce/trunk/modules/settings.php b/anytrack-for-woocommerce/trunk/modules/settings.php index 73962df..370f4c5 100644 --- a/anytrack-for-woocommerce/trunk/modules/settings.php +++ b/anytrack-for-woocommerce/trunk/modules/settings.php @@ -1,6 +1,5 @@ $value ){ $options[$key] = trim( sanitize_text_field( $value ) ); } + + // Validate before saving + $validation_result = $this->validateSave( $options ); + if( $validation_result !== true ){ + $this->message = '
' . $validation_result . '
'; + return; + } + update_option( $this->setttings_prefix.'_options', $options ); $this->message = '
'.__('Settings saved', $this->setttings_prefix ).'
'; @@ -26,6 +33,112 @@ function __construct( $prefix ){ } + function getWooCommerceIntegrationErrorMessage(){ + return __('Please install the WooCommerce integration through AnyTrack integrations catalog', $this->setttings_prefix ); + } + + function getInvalidPropertyIdErrorMessage(){ + return __('Invalid Property ID: Property does not exist', $this->setttings_prefix ); + } + + function isInvalidPropertyIdResponse( $body, $property_id ){ + if( empty( $body ) ){ + return false; + } + + $property_id_pattern = preg_quote( $property_id, '/' ); + $invalid_property_patterns = array( + '/Property\s+["\']?' . $property_id_pattern . '["\']?\s+(not exists anymore|does not exist|not found)/i', + '/console\.error\s*\(\s*["\'][^"\']*(not exists anymore|does not exist|not found)[^"\']*["\']\s*\)/i' + ); + + foreach( $invalid_property_patterns as $pattern ){ + if( preg_match( $pattern, $body ) ){ + return true; + } + } + + return false; + } + + function validateSave( $options ){ + // Check if property_id exists and is exactly 12 characters + if( !isset( $options['property_id'] ) || empty( $options['property_id'] ) ){ + return __('Property ID is required', $this->setttings_prefix ); + } + + $property_id = $options['property_id']; + if( strlen( $property_id ) !== 12 ){ + return __('Property ID must be exactly 12 characters', $this->setttings_prefix ); + } + + // Make API request to validate the property + $ANYTRACK_TRACKER_ENDPOINT = defined('ANYTRACK_TRACKER_ENDPOINT') ? ANYTRACK_TRACKER_ENDPOINT : 'https://t1.anytrack.io/assets/'; + $api_url = rtrim( $ANYTRACK_TRACKER_ENDPOINT, '/' ) . '/' . $property_id . '.js'; + + $response = wp_remote_get( $api_url, array( + 'timeout' => 15, + 'headers' => array( + 'Accept' => 'application/javascript' + ) + ) ); + + if( is_wp_error( $response ) ){ + return __('Failed to validate Property ID: ' . $response->get_error_message(), $this->setttings_prefix ); + } + + $body = wp_remote_retrieve_body( $response ); + $response_code = wp_remote_retrieve_response_code( $response ); + + if( $response_code !== 200 ){ + return __('Invalid Property ID: Unable to retrieve tracking script', $this->setttings_prefix ); + } + + if( $this->isInvalidPropertyIdResponse( $body, $property_id ) ){ + return $this->getInvalidPropertyIdErrorMessage(); + } + + // Parse JavaScript to check for WooCommerce integration + // Extract the last JSON object passed to AnyTrack function (the configuration) + if( preg_match('/AnyTrack["\']?\s*,\s*(\{.+\})\s*\)\s*;?\s*$/s', $body, $matches) ){ + $config_str = $matches[1]; + + // The config is already valid JSON in the response + $config = json_decode( $config_str, true ); + + if( json_last_error() === JSON_ERROR_NONE ){ + // Successfully parsed JSON, check for ig field + if( !isset( $config['ig'] ) || !is_array( $config['ig'] ) ){ + return $this->getWooCommerceIntegrationErrorMessage(); + } + + // Check if woocommerce integration exists + $has_woocommerce = false; + foreach( $config['ig'] as $integration ){ + if( isset( $integration['akid'] ) && $integration['akid'] === 'woocommerce' ){ + $has_woocommerce = true; + break; + } + } + + if( !$has_woocommerce ){ + return $this->getWooCommerceIntegrationErrorMessage(); + } + + return true; // Valid - WooCommerce integration found + } + } + + // Fallback: If JSON parsing fails, use simpler regex search + // This handles cases where the JS structure is different + if( preg_match('/"ig"\s*:\s*\[/s', $body) && preg_match('/"akid"\s*:\s*"woocommerce"/s', $body) ){ + return true; // Valid - found both ig array and woocommerce akid + } + + // Could not validate WooCommerce integration + return $this->getWooCommerceIntegrationErrorMessage(); + } + function get_setting( $setting_name ){ $inner_option = get_option( $this->setttings_prefix.'_options'); return $inner_option[$setting_name]; diff --git a/anytrack-for-woocommerce/trunk/readme.txt b/anytrack-for-woocommerce/trunk/readme.txt index bd4a729..8f484a4 100755 --- a/anytrack-for-woocommerce/trunk/readme.txt +++ b/anytrack-for-woocommerce/trunk/readme.txt @@ -4,7 +4,7 @@ Donate link: https://anytrack.io/ Tags: woocommerce, e-commerce, conversions, facebook, google, funnelkit Requires at least: 4.7 Tested up to: 6.8.1 -Stable tag: 1.5.6 +Stable tag: 1.5.8 Requires PHP: 7.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -77,6 +77,9 @@ prefer on the pixel settings on AnyTrack. Initial version. == Changelog == += 1.5.8 = +* Add property id validation + = 1.5.7 = * Restrict the event mapping to the default standards