diff --git a/changelog.txt b/changelog.txt index 00c05840c..8c9bfeb80 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,135 +1,141 @@ *** Facebook for WooCommerce Changelog *** -= 3.1.5 - 2023-11-29 = -* Fix - Remove mentions of shops. - -= 3.1.3 - 2023-11-07 = -* Fix - Doc - Use new Woo.com domain. -* Tweak - WC 8.3 compatibility. -* Tweak - WP 6.4 compatibility. - -= 3.1.2 - 2023-10-19 = -* Dev - Add phpcs on changed files only. - -= 3.1.1 - 2023-10-12 = -* Update - Revert "Advandtage+ Shoppings Ads support in Advertise tab". - -= 3.0.34 - 2023-10-05 = -* Add - Filter the size of the Facebook product image. -* Fix - AddToCart duplication when other plugins clone cart. -* Tweak - WC 8.2 compatibility. - -= 3.0.33 - 2023-09-05 = -* Dev - Updates PHP unit tests matrix in git workflow and versions of dev dependencies in composer. -* Fix - Issues with Facebook Sync status display while product filtering in admin. -* Tweak - WC 8.1 compatibility. - -= 3.0.32 - 2023-08-18 = -* Fix - Changes property access of product id from private to public. -* Fix - Eliminates dynamic property creation deprecation warnings. -* Fix - Update WPML compatibility to prevent fatal errors on PHP 8+. -* Tweak - Bump Marketing API version to v17.0. -* Tweak - Displays warnings on accessing private/protected properties incorrectly. - -= 3.0.31 - 2023-08-09 = -* Dev - Filters Business Manager ID. -* Fix - Fatal error when facebook_config option is empty. -* Fix - WC_Facebookcommerce_Pixel::get_options() throwing a fatal error if facebook_config is invalid. -* Tweak - Adds backward arrow to Facebook Product Sets backlink. -* Tweak - Update product data options icon. -* Tweak - WC 8.0 compatibility. -* Tweak - WP 6.3 compatibility. - -= 3.0.30 - 2023-08-01 = -* Dev - Add release preparation GH workflow. -* Fix - Facebook sync for newly published product without Google product category. -* Fix - Syncs products with All Caps title to Facebook and displays a warning in Facebook meta box. - -= 3.0.29 - 2023-07-18 = -* Fix - Corrects backlink to 'Go to Facebook Product Sets' in success notice on Edit Facebook Product Sets page. -* Tweak - Removes duplicate code. - -= 3.0.28 - 2023-07-13 = -* Add - Priority to enhanced catalog attributes and display as per priority. -* Fix - Woo category synced as Google Product category. - -= 3.0.27 - 2023-07-05 = -* Fix - Products are deleted from facebook once changed to draft. - -= 3.0.26 - 2023-06-28 = -* Tweak - WC 7.9 compatibility. - -= 3.0.25 - 2023-06-13 = -* Fix - Fatal error when Facebook.net returns an empty response. -* Fix - PHP Warning caused by array_filter() call. -* Fix - Remove assigned Google product category at individual product level. -* Tweak - WC 7.8 compatibility. - -= 3.0.24 - 2023-06-06 = -* Fix - Product variants weren't deleted correctly from the Facebook catalog in some instances. - -= 3.0.23 - 2023-05-09 = -* Fix - Delete product in the Facebook catalog when products are deleted via WC Rest API. - -= 3.0.22 - 2023-05-03 = -* Fix - Pixel code not activated on checkout. - -= 3.0.21 - 2023-05-02 = -* Fix - Issue in admin product search. - -= 3.0.20 - 2023-05-02 = -* Fix - Adds escaping to outputs and sanitizing to inputs. -* Tweak - WC 7.7 compatibility. - -= 3.0.19 - 2023-04-18 = -* Tweak - Bump Marketing API version from v16.0. - -= 3.0.18 - 2023-04-11 = -* Fix - Fatal error when facebook_config option is empty. -* Fix - Selected categories not showing on Product Sets edit page. - -= 3.0.17 - 2023-04-05 = -* Tweak - WC 7.6 compatibility. - -= 3.0.16 - 2023-03-21 = -* Fix - Deprecation notices thrown by nonce_user_logged_out. -* Fix - Display the Facebook tab and sync settings for external products. -* Fix - viewContent events triggering PHP server notices on elementor sites. - -= 3.0.15 - 2023-03-14 = -* Tweak - WC 7.5 compatibility. -* Tweak - WP 6.2 compatibility. - -= 3.0.14 - 2023-03-02 = -* Fix - Fatal error due to the latest WC Blocks changes. -* Fix custom attribute name with special characters breaks sync. - -= 3.0.13 - 2023-02-28 = -* Fix - WC()->session causing fatal error when the `woocommerce_add_to_cart_redirect` filter is called via REST API. - -= 3.0.12 - 2023-02-21 = -* Fix - Replace is_ajax calls with wp_doing_ajax(). -* Fix - out-of-stock products not deleted in Facebook catalog. - -= 3.0.11 - 2023-02-14 = -* Fix - Default sync mode on new product. - -= 3.0.10 - 2023-02-07 = -* Add - Ping Meta server with the currently installed plugin version. -* Fix - PHP 8.1 deprecated warnings. -* Tweak - WC 7.4 compatibility. - -= 3.0.9 - 2023-01-31 = -* Fix - CAPI purchase event not firing with orders from FB/Instagram app on iOS. -* Fix - Setting a product's Facebook sync status to "Do not sync" not working. -* Update - Onboarding task title and remove task content. - -= 3.0.8 - 2023-01-10 = -* Add - Add support for Mix and Match containers with per-item pricing. -* Dev - Fix phpcs violations in Framework/Api folder. -* Tweak - Facebook Marketing API from v13.0 to v14.0. -* Tweak - Use specific Bundles/Composites functions for calculating prices. += 3.1.6 - 2023-12-27 = +* Fix - Facebook Pixel events missing on redirect to cart. += 3.1.5 - 2023-11-29 = +* Fix - Remove mentions of shops. + += 3.1.4 - 2023-11-25 = +* Fix - Remove popup modal blocking product edit when product is using category excluded from sync. + += 3.1.3 - 2023-11-07 = +* Fix - Doc - Use new Woo.com domain. +* Tweak - WC 8.3 compatibility. +* Tweak - WP 6.4 compatibility. + += 3.1.2 - 2023-10-19 = +* Dev - Add phpcs on changed files only. + += 3.1.1 - 2023-10-12 = +* Update - Revert "Advandtage+ Shoppings Ads support in Advertise tab". + += 3.0.34 - 2023-10-05 = +* Add - Filter the size of the Facebook product image. +* Fix - AddToCart duplication when other plugins clone cart. +* Tweak - WC 8.2 compatibility. + += 3.0.33 - 2023-09-05 = +* Dev - Updates PHP unit tests matrix in git workflow and versions of dev dependencies in composer. +* Fix - Issues with Facebook Sync status display while product filtering in admin. +* Tweak - WC 8.1 compatibility. + += 3.0.32 - 2023-08-18 = +* Fix - Changes property access of product id from private to public. +* Fix - Eliminates dynamic property creation deprecation warnings. +* Fix - Update WPML compatibility to prevent fatal errors on PHP 8+. +* Tweak - Bump Marketing API version to v17.0. +* Tweak - Displays warnings on accessing private/protected properties incorrectly. + += 3.0.31 - 2023-08-09 = +* Dev - Filters Business Manager ID. +* Fix - Fatal error when facebook_config option is empty. +* Fix - WC_Facebookcommerce_Pixel::get_options() throwing a fatal error if facebook_config is invalid. +* Tweak - Adds backward arrow to Facebook Product Sets backlink. +* Tweak - Update product data options icon. +* Tweak - WC 8.0 compatibility. +* Tweak - WP 6.3 compatibility. + += 3.0.30 - 2023-08-01 = +* Dev - Add release preparation GH workflow. +* Fix - Facebook sync for newly published product without Google product category. +* Fix - Syncs products with All Caps title to Facebook and displays a warning in Facebook meta box. + += 3.0.29 - 2023-07-18 = +* Fix - Corrects backlink to 'Go to Facebook Product Sets' in success notice on Edit Facebook Product Sets page. +* Tweak - Removes duplicate code. + += 3.0.28 - 2023-07-13 = +* Add - Priority to enhanced catalog attributes and display as per priority. +* Fix - Woo category synced as Google Product category. + += 3.0.27 - 2023-07-05 = +* Fix - Products are deleted from facebook once changed to draft. + += 3.0.26 - 2023-06-28 = +* Tweak - WC 7.9 compatibility. + += 3.0.25 - 2023-06-13 = +* Fix - Fatal error when Facebook.net returns an empty response. +* Fix - PHP Warning caused by array_filter() call. +* Fix - Remove assigned Google product category at individual product level. +* Tweak - WC 7.8 compatibility. + += 3.0.24 - 2023-06-06 = +* Fix - Product variants weren't deleted correctly from the Facebook catalog in some instances. + += 3.0.23 - 2023-05-09 = +* Fix - Delete product in the Facebook catalog when products are deleted via WC Rest API. + += 3.0.22 - 2023-05-03 = +* Fix - Pixel code not activated on checkout. + += 3.0.21 - 2023-05-02 = +* Fix - Issue in admin product search. + += 3.0.20 - 2023-05-02 = +* Fix - Adds escaping to outputs and sanitizing to inputs. +* Tweak - WC 7.7 compatibility. + += 3.0.19 - 2023-04-18 = +* Tweak - Bump Marketing API version from v16.0. + += 3.0.18 - 2023-04-11 = +* Fix - Fatal error when facebook_config option is empty. +* Fix - Selected categories not showing on Product Sets edit page. + += 3.0.17 - 2023-04-05 = +* Tweak - WC 7.6 compatibility. + += 3.0.16 - 2023-03-21 = +* Fix - Deprecation notices thrown by nonce_user_logged_out. +* Fix - Display the Facebook tab and sync settings for external products. +* Fix - viewContent events triggering PHP server notices on elementor sites. + += 3.0.15 - 2023-03-14 = +* Tweak - WC 7.5 compatibility. +* Tweak - WP 6.2 compatibility. + += 3.0.14 - 2023-03-02 = +* Fix - Fatal error due to the latest WC Blocks changes. +* Fix custom attribute name with special characters breaks sync. + += 3.0.13 - 2023-02-28 = +* Fix - WC()->session causing fatal error when the `woocommerce_add_to_cart_redirect` filter is called via REST API. + += 3.0.12 - 2023-02-21 = +* Fix - Replace is_ajax calls with wp_doing_ajax(). +* Fix - out-of-stock products not deleted in Facebook catalog. + += 3.0.11 - 2023-02-14 = +* Fix - Default sync mode on new product. + += 3.0.10 - 2023-02-07 = +* Add - Ping Meta server with the currently installed plugin version. +* Fix - PHP 8.1 deprecated warnings. +* Tweak - WC 7.4 compatibility. + += 3.0.9 - 2023-01-31 = +* Fix - CAPI purchase event not firing with orders from FB/Instagram app on iOS. +* Fix - Setting a product's Facebook sync status to "Do not sync" not working. +* Update - Onboarding task title and remove task content. + += 3.0.8 - 2023-01-10 = +* Add - Add support for Mix and Match containers with per-item pricing. +* Dev - Fix phpcs violations in Framework/Api folder. +* Tweak - Facebook Marketing API from v13.0 to v14.0. +* Tweak - Use specific Bundles/Composites functions for calculating prices. + = 3.0.7 - 2023-01-03 = * Dev - Add node and npm version restrictions. * Dev - Ease current node version restrictions. diff --git a/facebook-commerce-events-tracker.php b/facebook-commerce-events-tracker.php index 8b6d5c3ca..cc4139dbb 100644 --- a/facebook-commerce-events-tracker.php +++ b/facebook-commerce-events-tracker.php @@ -116,9 +116,8 @@ private function add_hooks() { add_action( 'woocommerce_ajax_added_to_cart', array( $this, 'add_filter_for_add_to_cart_fragments' ) ); // AddToCart while using redirect to cart page if ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add', 'no' ) ) { - add_filter( 'woocommerce_add_to_cart_redirect', array( $this, 'set_last_product_added_to_cart_upon_redirect' ), 10, 2 ); - add_action( 'woocommerce_ajax_added_to_cart', array( $this, 'set_last_product_added_to_cart_upon_ajax_redirect' ) ); - add_action( 'woocommerce_after_cart', array( $this, 'inject_add_to_cart_redirect_event' ), 10, 2 ); + add_action( 'wp_head', array( WC_Facebookcommerce_Utils::class, 'print_deferred_events' ) ); + add_action( 'shutdown', array( WC_Facebookcommerce_Utils::class, 'save_deferred_events' ) ); } // InitiateCheckout events @@ -563,8 +562,12 @@ public function inject_add_to_cart_event( $cart_item_key, $product_id, $quantity return; } + /** + * Make sure to proceed only if the cart item exists. + * Some other plugins may clone the WC_Cart object. Calling clone APIs may trigger the 'woocommerce_add_to_cart' action. + * We want to make sure to proceed only if the cart item exists inside the original WC_Cart object. + */ $cart = WC()->cart; - // Check if we're dealing with cloned cart if ( ! isset( $cart->cart_contents[ $cart_item_key ] ) ) { return; } @@ -736,86 +739,6 @@ public function add_conditional_add_to_cart_event_fragment( $fragments ) { return $fragments; } - - /** - * Sets last product added to cart to session when adding to cart a product and redirection to cart is enabled. - * - * @internal - * - * @since 1.10.2 - * - * @param string $redirect URL redirecting to (usually cart) - * @param null|\WC_Product $product the product just added to the cart - * @return string - */ - public function set_last_product_added_to_cart_upon_redirect( $redirect, $product = null ) { - - // Bail if the session variable has been set or WC()->session is null. - if ( ! isset( WC()->session ) || WC()->session->get( 'facebook_for_woocommerce_last_product_added_to_cart', 0 ) > 0 ) { - return $redirect; - } - - $product_id = 0; - - if ( $product instanceof \WC_Product ) { - $product_id = isset( $_POST['variation_id'] ) ? wc_clean( wp_unslash( $_POST['variation_id'] ) ) : $product->get_id(); - } elseif ( isset( $_GET['add-to-cart'] ) && is_numeric( wc_clean( wp_unslash( $_GET['add-to-cart'] ) ) ) ) { - $product_id = wc_clean( wp_unslash( $_GET['add-to-cart'] ) ); - } - - WC()->session->set( 'facebook_for_woocommerce_last_product_added_to_cart', (int) $product_id ); - - return $redirect; - - } - - - /** - * Sets last product added to cart to session when adding a product to cart from an archive page and both AJAX adding and redirection to cart are enabled. - * - * @internal - * - * @since 1.10.2 - * - * @param null|int $product_id the ID of the product just added to the cart - */ - public function set_last_product_added_to_cart_upon_ajax_redirect( $product_id = null ) { - - if ( ! $product_id ) { - facebook_for_woocommerce()->log( 'Cannot record AddToCart event because the product cannot be determined. Backtrace: ' . print_r( wp_debug_backtrace_summary(), true ) ); - return; - } - - $product = wc_get_product( $product_id ); - - if ( $product instanceof \WC_Product ) { - WC()->session->set( 'facebook_for_woocommerce_last_product_added_to_cart', $product->get_id() ); - } - } - - - /** - * Triggers an AddToCart event when redirecting to the cart page. - * - * @internal - */ - public function inject_add_to_cart_redirect_event() { - - if ( ! $this->is_pixel_enabled() ) { - return; - } - - $last_product_id = WC()->session->get( 'facebook_for_woocommerce_last_product_added_to_cart', 0 ); - - if ( $last_product_id > 0 ) { - - $this->inject_add_to_cart_event( '', $last_product_id, 1, 0 ); - - WC()->session->set( 'facebook_for_woocommerce_last_product_added_to_cart', 0 ); - } - } - - /** * Triggers an InitiateCheckout event when customer reaches checkout page. * diff --git a/facebook-commerce-pixel-event.php b/facebook-commerce-pixel-event.php index 2a78fd81b..f8d621004 100644 --- a/facebook-commerce-pixel-event.php +++ b/facebook-commerce-pixel-event.php @@ -285,15 +285,20 @@ public function get_event_script( $event_name, $params, $method = 'track' ) { * @param string $method Name of the pixel's fbq() function to call. */ public function inject_event( $event_name, $params, $method = 'track' ) { - - if ( \WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) { - \WC_Facebookcommerce_Utils::wc_enqueue_js( $this->get_event_code( $event_name, self::build_params( $params, $event_name ), $method ) ); + // If we have add to cart redirect enabled, we must defer the events to render them the next page load. + $should_defer = 'yes' === get_option( 'woocommerce_cart_redirect_after_add', 'no' ); + if ( WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) { + $code = $this->get_event_code( $event_name, self::build_params( $params, $event_name ), $method ); + if ( $should_defer ) { + WC_Facebookcommerce_Utils::add_deferred_event( $code ); + } else { + WC_Facebookcommerce_Utils::wc_enqueue_js( $code ); + } } else { printf( $this->get_event_script( $event_name, self::build_params( $params, $event_name ), $method ) ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped } } - /** * Gets the JavaScript code to track a conditional event wrapped in '; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped --- Printing hardcoded JS tracking code. + } + } + + /** + * Loads deferred events from the storage and cleans the storage immediately after. + * + * @return array + * + * @since 3.1.6 + */ + private static function load_deferred_events(): array { + $transient_key = static::get_deferred_events_transient_key(); + if ( ! $transient_key ) { + return array(); + } + + $deferred_events = get_transient( $transient_key ); + if ( ! $deferred_events ) { + return array(); + } + + delete_transient( $transient_key ); + return $deferred_events; + } + + /** + * Adds event into the list of events to be saved/rendered. + * + * @param string $code Generated JS code string w/o a script tag. + * + * @return void + * + * @since 3.1.6 + */ + public static function add_deferred_event( string $code ): void { + static::$deferred_events[] = $code; + } + + /** + * Saves deferred events into the storage. + * + * @return void + * + * @since 3.1.6 + */ + public static function save_deferred_events() { + $transient_key = static::get_deferred_events_transient_key(); + if ( ! $transient_key ) { + return; + } + + $existing_events = static::load_deferred_events(); + static::$deferred_events = array_merge( $existing_events, static::$deferred_events ); + + if ( ! empty( static::$deferred_events ) ) { + set_transient( $transient_key, static::$deferred_events, DAY_IN_SECONDS ); + } + } + + /** + * Returns the transient key for deferred events based on user session. + * + * @return string + * + * @since 3.1.6 + */ + private static function get_deferred_events_transient_key(): string { + if ( is_object( WC()->session ) ) { + return 'facebook_for_woocommerce_async_events_' . md5( WC()->session->get_customer_id() ); + } + return ''; + } + /** * WooCommerce 2.1 support for wc_enqueue_js * @@ -54,6 +148,7 @@ class WC_Facebookcommerce_Utils { public static function wc_enqueue_js( $code ) { global $wc_queued_js; + // Immediately renders code in the footer. if ( function_exists( 'wc_enqueue_js' ) && empty( $wc_queued_js ) ) { wc_enqueue_js( $code ); } else { diff --git a/package-lock.json b/package-lock.json index 65bd6b88e..cf5aa29f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "facebook-for-woocommerce", - "version": "3.1.5", + "version": "3.1.6", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 22528679a..77783a700 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "facebook-for-woocommerce", - "version": "3.1.5", + "version": "3.1.6", "author": "Facebook", "homepage": "https://woo.com/products/facebook/", "license": "GPL-2.0", @@ -19,7 +19,8 @@ "archive": "composer archive --file=$npm_package_name --format=zip", "postarchive": "rm -rf $npm_package_name && unzip $npm_package_name.zip -d $npm_package_name && rm $npm_package_name.zip && zip -r $npm_package_name.zip $npm_package_name && rm -rf $npm_package_name", "prebuild": "composer install", - "build": "npm run build:assets && npm run i18n", + "build:dev": "npm run build:assets && npm run i18n", + "build": "npm run build:dev", "postbuild": "npm run archive", "i18n": "WP_CLI_PHP_ARGS='-d memory_limit=2048M' ./vendor/bin/wp i18n make-pot ./ i18n/languages/$npm_package_name.pot --slug=$npm_package_name --domain=$npm_package_name --exclude=bin,data,node_modules,tests,vendor", "generate:category_attribute_json": "php bin/GenerateCategoryAttributeMapping.php", diff --git a/readme.txt b/readme.txt index 234cac76b..ee2c63ce4 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: facebook, automattic, woothemes Tags: facebook, shop, catalog, advertise, pixel, product Requires at least: 4.4 Tested up to: 6.4 -Stable tag: 3.1.5 +Stable tag: 3.1.6 Requires PHP: 5.6 or greater MySQL: 5.6 or greater License: GPLv2 or later @@ -40,9 +40,15 @@ When opening a bug on GitHub, please give us as many details as possible. == Changelog == -= 3.1.5 - 2023-11-29 = -* Fix - Remove mentions of shops. += 3.1.6 - 2023-12-27 = +* Fix - Facebook Pixel events missing on redirect to cart. += 3.1.5 - 2023-11-29 = +* Fix - Remove mentions of shops. + += 3.1.4 - 2023-11-25 = +* Fix - Remove popup modal blocking product edit when product is using category excluded from sync. + = 3.1.3 - 2023-11-07 = * Fix - Doc - Use new Woo.com domain. * Tweak - WC 8.3 compatibility.