<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Code Example Archives - WooCommerce Global Cart - Single Site</title>
	<atom:link href="https://single-site.wpglobalcart.com/documentation_tag/code-example/feed/" rel="self" type="application/rss+xml" />
	<link>https://single-site.wpglobalcart.com/documentation_tag/code-example/</link>
	<description></description>
	<lastBuildDate>Wed, 16 Sep 2026 08:18:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>
	<item>
		<title>Daily Currency Price updates for the Synchronized Products</title>
		<link>https://single-site.wpglobalcart.com/documentation/daily-currency-price-updates-for-the-synchronized-products/</link>
					<comments>https://single-site.wpglobalcart.com/documentation/daily-currency-price-updates-for-the-synchronized-products/#respond</comments>
		
		<dc:creator><![CDATA[admin-woogc]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 07:56:27 +0000</pubDate>
				<guid isPermaLink="false">https://single-site.wpglobalcart.com/?post_type=documentation&#038;p=16217</guid>

					<description><![CDATA[<p>When using WP Global Cart to synchronize products between WooCommerce shops that use different currencies, the same product may need to have a different price on each shop. For example, a product may have an original price of €100 EUR on the main shop, while...</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/daily-currency-price-updates-for-the-synchronized-products/">Daily Currency Price updates for the Synchronized Products</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>When using WP Global Cart to synchronize products between WooCommerce shops that use different currencies, the same product may need to have a different price on each shop.</p>
<p>For example, a product may have an original price of <strong>€100 EUR</strong> on the main shop, while another synchronized shop uses <strong>USD</strong>. The product on the second shop should have its price automatically converted to the local currency.</p>
<p>The <strong>Daily Currency Price Synchronization</strong> code provides a simple way to keep these prices updated automatically.</p>
<h4>How It Works</h4>
<p>When a product is synchronized to another shop using the WP Global Cart <strong>Product Synchronisation</strong> functionality, two additional pieces of information are sent along with the product:</p>
<ul>
<li><strong>Origin product currency</strong> – the currency used by the original shop.</li>
<li><strong>Origin product price</strong> – the original product price in that currency.</li>
</ul>
<p>These values are stored with the synchronized product as:</p>
<pre><code>_origin_product_currency
_origin_product_price</code></pre>
<p>The destination shop then uses this information to calculate the correct price in its own WooCommerce currency.</p>
<p>For example:</p>
<p><strong>Origin shop:</strong></p>
<pre><code>Price:    100 EUR
Currency: EUR</code></pre>
<p><strong>Destination shop:</strong></p>
<pre><code>Currency: USD
Price:    automatically converted from 100 EUR</code></pre>
<p>The conversion is performed using the lightweight <a href="https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/"><code><strong>WOOGC_Currency_Converter</strong></code> class</a>, which uses European Central Bank (ECB) exchange rates. This means there is no need to install an additional currency converter or multi-currency plugin for this functionality. [<a href="https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/">article here</a>]</p>
<h4>Automatic Daily Updates</h4>
<p>The price synchronization runs automatically once per day ( or custom-defined). It takes the stored <strong>origin price</strong> and converts it to the current currency of the local WooCommerce shop.</p>
<p>This is important because the conversion is always performed from the original price, rather than converting the previously converted price. As exchange rates change, the local product price can therefore be updated accordingly without accumulating conversion errors.</p>
<p>The solution works with WooCommerce <strong>simple products, variable products, and product variations</strong>, allowing synchronized product catalogs to maintain appropriate local prices.</p>
<h4>Ideal for Multi-Shop Stores</h4>
<p>This feature is particularly useful when a WP Global Cart network contains shops operating with different currencies. Each shop can maintain its own local WooCommerce currency while synchronized products automatically receive prices converted from their original shop currency.</p>
<p>This provides a lightweight solution for maintaining consistent and up-to-date product pricing across a multi-currency WooCommerce network.</p>
<p>The code should be placed inside a custom file in the /wp-content/mu-plugins/ folder.</p>
<pre class="brush: php; collapse: true; light: false; title: ; toolbar: true; notranslate">

    /**
     * Scheduled currency price sync for WooCommerce products.
     *
     * Runs on a recurring WP-Cron schedule (default: once per day) and updates
     * the price of every product — simple, variable (per variation), external,
     * grouped, etc. — that carries both the &#039;_origin_product_currency&#039; and
     * &#039;_origin_product_price&#039; meta keys, converting the stored origin price
     * into the shop&#039;s current currency via WOOGC_Currency_Converter::convert().
     *
     * Products/variations missing EITHER meta key are skipped and the loop
     * continues to the next one.
     *
     * USAGE:
     * Paste this into a custom/mu-plugin file, or into your theme&#039;s
     * functions.php. Requires the plugin that provides WOOGC_Currency_Converter
     * to be active.
     */

    if ( ! defined( &#039;ABSPATH&#039; ) ) {
	    exit;
    }

    define( &#039;CUSTOM_PRICE_SYNC_HOOK&#039;, &#039;custom_price_sync_cron_hook&#039; );
    
    
    add_filter( &#039;woogc/ps/synchronize_product/origin_product/meta_data&#039;, &#039;custom_woogc_add_site_currency&#039;, 10, 1 );
    function custom_woogc_add_site_currency( $args )
        {
            $product    =   wc_get_product( $args&#x5B; &#039;origin_product_id&#039; ] );
            
            $args&#x5B;&#039;product_meta&#039;]&#x5B;&#039;_origin_product_currency&#039;]&#x5B;] = get_option( &#039;woocommerce_currency&#039; );
            $args&#x5B;&#039;product_meta&#039;]&#x5B;&#039;_origin_product_price&#039;]&#x5B;]    = $product-&gt;get_price();

            return $args;
        }
        

    /**
     *
     * Change the interval via the &#039;custom_price_sync_interval_seconds&#039; filter,
     * e.g. add_filter( &#039;custom_price_sync_interval_seconds&#039;, fn() =&gt; HOUR_IN_SECONDS * 6 );
     *
     * NOTE: if you change this after the event is already scheduled, run
     * custom_price_sync_unschedule_event() once (or deactivate/reactivate)
     * so WordPress picks up the new interval — WP doesn&#039;t reschedule an
     * already-queued event automatically.
     */
    add_filter( &#039;cron_schedules&#039;, &#039;custom_price_sync_register_interval&#039; );
    function custom_price_sync_register_interval( $schedules ) {
	    $schedules&#x5B;&#039;custom_price_sync_interval&#039;] = array(
		    &#039;interval&#039; =&gt; apply_filters( &#039;custom_price_sync_interval_seconds&#039;, DAY_IN_SECONDS ),
		    &#039;display&#039;  =&gt; __( &#039;Custom Price Sync Interval&#039;, &#039;custom-price-sync&#039; ),
	    );
	    return $schedules;
    }

    /**
     * Schedule the event if it isn&#039;t already scheduled.
     */
    add_action( &#039;init&#039;, &#039;custom_price_sync_schedule_event&#039; );
    function custom_price_sync_schedule_event() {
	    if ( ! wp_next_scheduled( CUSTOM_PRICE_SYNC_HOOK ) ) {
		    wp_schedule_event( time(), &#039;custom_price_sync_interval&#039;, CUSTOM_PRICE_SYNC_HOOK );
	    }
    }

    /**
     * Unschedule helper — call this from a plugin deactivation hook if you turn
     * this into its own plugin file:
     *   register_deactivation_hook( __FILE__, &#039;custom_price_sync_unschedule_event&#039; );
     */
    function custom_price_sync_unschedule_event() {
	    $timestamp = wp_next_scheduled( CUSTOM_PRICE_SYNC_HOOK );
	    if ( $timestamp ) {
		    wp_unschedule_event( $timestamp, CUSTOM_PRICE_SYNC_HOOK );
	    }
    }

    /**
     * The cron callback: loops through every product in batches and updates
     * prices for any product/variation carrying the origin currency/price meta.
     */
    add_action( CUSTOM_PRICE_SYNC_HOOK, &#039;custom_price_sync_run&#039; );
    function custom_price_sync_run() {

	    if ( ! class_exists( &#039;WOOGC_Currency_Converter&#039; ) ) {
		    custom_price_sync_log( &#039;WOOGC_Currency_Converter class not found. Aborting sync.&#039; );
		    return;
	    }

	    $batch_size = apply_filters( &#039;custom_price_sync_batch_size&#039;, 300 );
	    $paged      = 1;

	    do {
		    $query = new WP_Query( array(
			    &#039;post_type&#039;              =&gt; &#039;product&#039;,
			    &#039;post_status&#039;            =&gt; &#039;publish&#039;,
			    &#039;posts_per_page&#039;         =&gt; $batch_size,
			    &#039;paged&#039;                  =&gt; $paged,
			    &#039;fields&#039;                 =&gt; &#039;ids&#039;,
			    &#039;orderby&#039;                =&gt; &#039;ID&#039;,
			    &#039;order&#039;                  =&gt; &#039;ASC&#039;,
			    &#039;no_found_rows&#039;          =&gt; true,
			    &#039;update_post_meta_cache&#039; =&gt; false,
			    &#039;update_post_term_cache&#039; =&gt; false,
		    ) );

		    if ( empty( $query-&gt;posts ) ) {
			    break;
		    }

		    foreach ( $query-&gt;posts as $product_id ) {

			    $product = wc_get_product( $product_id );

			    if ( ! $product ) {
				    continue;
			    }

			    if ( $product-&gt;is_type( &#039;variable&#039; ) ) {

				    $updated_any_variation = false;

				    foreach ( $product-&gt;get_children() as $variation_id ) {
					    $variation = wc_get_product( $variation_id );

					    if ( ! $variation ) {
						    continue;
					    }

					    if ( custom_price_sync_maybe_update_product( $variation ) ) {
						    $updated_any_variation = true;
					    }
				    }

				    // Refresh the parent&#039;s cached price range after variations change.
				    if ( $updated_any_variation &amp;&amp; class_exists( &#039;WC_Product_Variable&#039; ) ) {
					    WC_Product_Variable::sync( $product_id );
					    wc_delete_product_transients( $product_id );
				    }
			    } else {
				    // Simple, external, grouped, etc.
				    custom_price_sync_maybe_update_product( $product );
			    }
		    }

		    $paged++;

	    } while ( true );

	    custom_price_sync_log( &#039;Price sync run completed.&#039; );
    }

    /**
     * Updates a single product/variation&#039;s price from its origin currency/price
     * meta, if both metas exist. Returns true if the price was updated.
     *
     * @param WC_Product $product
     * @return bool
     */
    function custom_price_sync_maybe_update_product( $product ) {

	    $product_id = $product-&gt;get_id();

	    // Skip products that don&#039;t have BOTH meta keys set (this is the correct
	    // existence check — get_post_meta()/get_meta() return &#039;&#039; both when a
	    // meta is missing AND when it&#039;s set to an empty string).
	    if ( ! metadata_exists( &#039;post&#039;, $product_id, &#039;_origin_product_currency&#039; )
		    || ! metadata_exists( &#039;post&#039;, $product_id, &#039;_origin_product_price&#039; ) ) {
		    return false;
	    }

	    $origin_currency = $product-&gt;get_meta( &#039;_origin_product_currency&#039;, true );
	    $origin_price    = $product-&gt;get_meta( &#039;_origin_product_price&#039;, true );

	    if ( &#039;&#039; === $origin_currency || &#039;&#039; === $origin_price || ! is_numeric( $origin_price ) ) {
		    custom_price_sync_log( sprintf( &#039;Product #%d has invalid origin meta, skipping.&#039;, $product_id ) );
		    return false;
	    }

	    $shop_currency = get_option( &#039;woocommerce_currency&#039; );

	    // Nothing to convert if origin currency already matches the shop currency.
	    if ( $origin_currency === $shop_currency ) {
		    $new_price = floatval( $origin_price );
	    } else {
		    $new_price = WOOGC_Currency_Converter::convert(
			    floatval( $origin_price ),
			    $origin_currency,
			    $shop_currency
		    );

		    if ( false === $new_price ) {
			    custom_price_sync_log( sprintf(
				    &#039;Currency conversion failed for product #%d (%s -&gt; %s), skipping.&#039;,
				    $product_id,
				    $origin_currency,
				    $shop_currency
			    ) );
			    return false;
		    }
	    }

	    $new_price = wc_format_decimal( $new_price, wc_get_price_decimals() );

	    $old_regular_price = $product-&gt;get_regular_price();
	    $old_sale_price    = $product-&gt;get_sale_price();

	    $product-&gt;set_regular_price( $new_price );

	    // If there&#039;s no active sale price, keep the active price in sync too.
	    // (If a sale price exists, we leave it as-is rather than guessing a new one.)
	    if ( &#039;&#039; === $old_sale_price ) {
		    $product-&gt;set_price( $new_price );
	    }

	    $product-&gt;save();

	    custom_price_sync_log( sprintf(
		    &#039;Product #%d price updated: %s %s -&gt; %s %s (regular price %s -&gt; %s).&#039;,
		    $product_id,
		    $origin_price,
		    $origin_currency,
		    $new_price,
		    $shop_currency,
		    $old_regular_price,
		    $new_price
	    ) );

	    return true;
    }

    /**
     * Simple logging helper — writes to WooCommerce &gt; Status &gt; Logs
     * (source: custom-price-sync). Disable with:
     *   add_filter( &#039;custom_price_sync_enable_logging&#039;, &#039;__return_false&#039; );
     */
    function custom_price_sync_log( $message ) {
	    if ( ! apply_filters( &#039;custom_price_sync_enable_logging&#039;, true ) ) {
		    return;
	    }

	    if ( function_exists( &#039;wc_get_logger&#039; ) ) {
		    wc_get_logger()-&gt;info( $message, array( &#039;source&#039; =&gt; &#039;custom-price-sync&#039; ) );
	    }
    }
</pre>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/daily-currency-price-updates-for-the-synchronized-products/">Daily Currency Price updates for the Synchronized Products</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://single-site.wpglobalcart.com/documentation/daily-currency-price-updates-for-the-synchronized-products/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Currency Conversion Using 3rd Exchange Rates</title>
		<link>https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/</link>
					<comments>https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/#respond</comments>
		
		<dc:creator><![CDATA[admin-woogc]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 07:30:28 +0000</pubDate>
				<guid isPermaLink="false">https://single-site.wpglobalcart.com/?post_type=documentation&#038;p=16215</guid>

					<description><![CDATA[<p>When using WooCommerce shops with different currencies, product prices often need to be converted from the currency of the original product to the currency used by the destination shop. The WOOGC_Currency_Converter class included with WP Global Cart provides a simple way to perform these conversions...</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/">Currency Conversion Using 3rd Exchange Rates</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p data-pm-slice="1 1 []">When using WooCommerce shops with different currencies, product prices often need to be converted from the currency of the original product to the currency used by the destination shop. The <strong>WOOGC_Currency_Converter</strong> class included with WP Global Cart provides a simple way to perform these conversions without requiring an additional currency conversion plugin.</p>
<p>The class uses the <strong>European Central Bank (ECB) reference exchange rates</strong> as its source. ECB rates are published against the Euro, allowing the class to convert between any two supported currencies indirectly through EUR. For example, a product priced in RON can be converted to USD using the EUR/RON and EUR/USD rates. The rates are stored in WordPress options and reused between updates, so a temporary failure of the ECB service does not prevent conversions from working.</p>
<p>Conversion is performed with a simple function call:</p>
<pre><code class="language-php">$value = WOOGC_Currency_Converter::convert(
    $amount,
    $from_currency,
    $to_currency
);</code></pre>
<p>For example:</p>
<pre><code class="language-php">$value = WOOGC_Currency_Converter::convert(
    100,
    'EUR',
    'USD'
);</code></pre>
<p>This approach can eliminate the need for dedicated WooCommerce multi-currency plugins such as <strong>Aelia Currency Switcher</strong>, <strong>FOX Currency Switcher</strong>, or WooCommerce&#8217;s own Multicurrency extension when your requirement is simply to convert product prices programmatically rather than provide a customer-facing currency switcher. Aelia Currency Switcher is a premium product, while FOX follows a free/premium model with additional features available in its paid version.</p>
<p>The class is particularly useful with <strong>WP Global Cart</strong>, where products can originate from one WooCommerce shop while being synchronized to another shop using a different currency. The original product currency and price can be retained, and the destination shop can calculate its local price automatically using the latest stored ECB rates.</p>
<p>This keeps the currency conversion logic lightweight, avoids adding another plugin dependency, and allows WP Global Cart to control the conversion process directly as part of product synchronization.</p>
<p>The code should be placed inside a custom file in the /wp-content/mu-plugins/ folder.</p>
<pre class="brush: php; title: ; notranslate">
    /**
     * WP Global Cart - ECB Currency Converter
     *
     * Retrieves Euro foreign exchange reference rates from the ECB
     * and converts amounts between currencies using EUR as the base.
     */
    class WOOGC_Currency_Converter {

        /**
         * ECB daily XML feed.
         */
        const ECB_FEED_URL = &#039;https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml&#039;;

        /**
         * WordPress option used to store the rates.
         */
        const OPTION_RATES = &#039;woogc_ecb_currency_rates&#039;;

        /**
         * WordPress option used to store the date of the last
         * successfully downloaded ECB rates.
         */
        const OPTION_DATE = &#039;woogc_ecb_currency_rates_date&#039;;

        /**
         * WordPress option used to store the last update timestamp.
         */
        const OPTION_UPDATED = &#039;woogc_ecb_currency_rates_updated&#039;;

        /**
         * Convert an amount from one currency to another.
         *
         * Example:
         * 100 EUR -&gt; USD
         * 100 RON -&gt; USD
         *
         * @param float  $amount
         * @param string $from_currency
         * @param string $to_currency
         *
         * @return float|false
         */
        public static function convert( $amount, $from_currency, $to_currency ) {

            $amount = (float) $amount;

            $from_currency = strtoupper( trim( $from_currency ) );
            $to_currency   = strtoupper( trim( $to_currency ) );

            // Nothing to convert.
            if ( $from_currency === $to_currency ) {
                return $amount;
            }

            // Make sure we have current rates, or the latest available rates.
            $rates = self::get_rates();

            if ( ! is_array( $rates ) || empty( $rates ) ) {
                return false;
            }

            /*
             * EUR is the base currency.
             *
             * Example:
             * EUR = 1
             * USD = 1.1551
             * RON = 5.2568
             */
            $from_rate = 1.0;
            $to_rate   = 1.0;

            /*
             * Currency other than EUR must exist in the ECB rates.
             */
            if ( &#039;EUR&#039; !== $from_currency ) {

                if ( ! isset( $rates&#x5B; $from_currency ] ) ) {
                    return false;
                }

                $from_rate = (float) $rates&#x5B; $from_currency ];
            }

            if ( &#039;EUR&#039; !== $to_currency ) {

                if ( ! isset( $rates&#x5B; $to_currency ] ) ) {
                    return false;
                }

                $to_rate = (float) $rates&#x5B; $to_currency ];
            }

            /*
             * Convert:
             *
             * source currency -&gt; EUR -&gt; target currency
             *
             * Example RON -&gt; USD:
             *
             * 100 / 5.2568 * 1.1551
             */
            return ( $amount / $from_rate ) * $to_rate;
        }

        /**
         * Get the currently stored ECB rates.
         *
         * This will attempt to update the rates once per day.
         * If today&#039;s update is unavailable, the previously stored
         * successful rates are returned.
         *
         * @return array|false
         */
        public static function get_rates() {

            $stored_rates = get_option( self::OPTION_RATES, array() );
            $stored_date  = get_option( self::OPTION_DATE, &#039;&#039; );

            /*
             * If we already have rates downloaded today, use them.
             */
            $today = current_time( &#039;Y-m-d&#039; );

            if (
                ! empty( $stored_rates ) &amp;&amp;
                $stored_date === $today
            ) {
                return $stored_rates;
            }

            /*
             * Try to download fresh ECB rates.
             */
            $new_rates = self::update_rates();

            /*
             * Successful update.
             */
            if ( is_array( $new_rates ) &amp;&amp; ! empty( $new_rates ) ) {
                return $new_rates;
            }

            /*
             * ECB unavailable / no new rates today.
             *
             * Fall back to the last successful rates.
             */
            if ( ! empty( $stored_rates ) ) {
                return $stored_rates;
            }

            return false;
        }

        /**
         * Download and store the latest ECB rates.
         *
         * @return array|false
         */
        public static function update_rates() {

            $response = wp_remote_get(
                self::ECB_FEED_URL,
                array(
                    &#039;timeout&#039;     =&gt; 15,
                    &#039;redirection&#039; =&gt; 3,
                    &#039;sslverify&#039;   =&gt; true,
                    &#039;headers&#039;     =&gt; array(
                        &#039;Accept&#039; =&gt; &#039;application/xml,text/xml&#039;,
                    ),
                )
            );

            if ( is_wp_error( $response ) ) {
                return false;
            }

            $status_code = wp_remote_retrieve_response_code( $response );

            if ( 200 !== $status_code ) {
                return false;
            }

            $body = wp_remote_retrieve_body( $response );

            if ( empty( $body ) ) {
                return false;
            }

            /*
             * Prevent XML external entity processing.
             */
            libxml_use_internal_errors( true );

            $xml = simplexml_load_string(
                $body,
                &#039;SimpleXMLElement&#039;,
                LIBXML_NONET | LIBXML_NOCDATA
            );

            if ( false === $xml ) {
                libxml_clear_errors();
                return false;
            }

            libxml_clear_errors();

            $rates = array(
                &#039;EUR&#039; =&gt; 1.0,
            );

            /*
             * ECB XML structure:
             *
             * &lt;Cube currency=&quot;USD&quot; rate=&quot;1.1551&quot;/&gt;
             */
            $currency_nodes = $xml-&gt;xpath(
                &#039;//*&#x5B;local-name()=&quot;Cube&quot;]&#x5B;@currency and @rate]&#039;
            );

            if ( empty( $currency_nodes ) ) {
                return false;
            }

            foreach ( $currency_nodes as $node ) {

                $currency = strtoupper( (string) $node&#x5B;&#039;currency&#039;] );
                $rate     = (float) $node&#x5B;&#039;rate&#039;];

                if ( empty( $currency ) || $rate &lt;= 0 ) {
                    continue;
                }

                $rates&#x5B; $currency ] = $rate;
            }

            /*
             * Make sure we got a reasonable set of rates.
             */
            if ( count( $rates ) &lt; 2 ) {
                return false;
            }

            /*
             * Save only after successfully parsing the complete feed.
             *
             * This is important: a failed/invalid request must never
             * overwrite the last known-good rates.
             */
            $today = current_time( &#039;Y-m-d&#039; );

            update_option(
                self::OPTION_RATES,
                $rates,
                false
            );

            update_option(
                self::OPTION_DATE,
                $today,
                false
            );

            update_option(
                self::OPTION_UPDATED,
                time(),
                false
            );

            return $rates;
        }

        /**
         * Get information about the currently stored rates.
         *
         * Useful for debugging/admin UI.
         *
         * @return array
         */
        public static function get_status() {

            return array(
                &#039;date&#039;    =&gt; get_option( self::OPTION_DATE, &#039;&#039; ),
                &#039;updated&#039; =&gt; get_option( self::OPTION_UPDATED, 0 ),
                &#039;rates&#039;   =&gt; get_option( self::OPTION_RATES, array() ),
            );
        }
    } 
</pre>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/">Currency Conversion Using 3rd Exchange Rates</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://single-site.wpglobalcart.com/documentation/currency-conversion-using-3rd-exchange-rates/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>woogc/ps/synchronize_product/child_product</title>
		<link>https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-child_product/</link>
					<comments>https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-child_product/#respond</comments>
		
		<dc:creator><![CDATA[admin-woogc]]></dc:creator>
		<pubDate>Tue, 15 Sep 2026 12:55:50 +0000</pubDate>
				<guid isPermaLink="false">https://single-site.wpglobalcart.com/?post_type=documentation&#038;p=16213</guid>

					<description><![CDATA[<p>Name: woogc/ps/synchronize_product/child_product Type: Filter Arguments: (object) $child_product (array) $main_product_data (int) $origin_product_blog_ID The woogc/ps/synchronize_product/child_product filter allows developers to modify the child product object immediately before it is returned to the WooCommerce Global Cart product synchronization process and saved on the destination shop. This provides an opportunity...</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-child_product/">woogc/ps/synchronize_product/child_product</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Name:</strong> woogc/ps/synchronize_product/child_product<br />
<strong>Type:</strong> Filter<br />
<strong>Arguments:</strong><br />
(object) $child_product<br />
(array) $main_product_data<br />
(int) $origin_product_blog_ID</p>
<p>The <code>woogc/ps/synchronize_product/child_product</code> filter allows developers to modify the <strong>child product object</strong> immediately before it is returned to the WooCommerce Global Cart product synchronization process and saved on the destination shop.</p>
<p>This provides an opportunity to customize the synchronized product after the child product has been created or updated, but before the synchronization process completes.</p>
<p>The filter can be used to change standard WooCommerce product properties, add or modify custom metadata, synchronize additional product information, or implement custom business logic for individual child shops.</p>
<p><strong>Arguments</strong></p>
<p><code><strong>$child_product</strong></code></p>
<p>A <code>WC_Product</code> object representing the product on the destination/child shop. This is the object that can be modified using the standard WooCommerce product methods, such as:</p>
<pre class="brush: php; title: ; notranslate">
$child_product&gt;set_price( $price );
$child_product&gt;set_stock_quantity( $quantity );
$child_product&gt;set_status( &#039;publish&#039; );
$child_product&gt;update_meta_data( &#039;_custom_field&#039;, $value );
</pre>
<p><code><strong>$main_product_data</strong></code></p>
<p>An array containing the synchronized data of the origin/main product. This can be used to inspect information received from the source product and apply additional logic to the child product.</p>
<p><code><strong>$origin_product_blog_ID</strong></code></p>
<p>The WordPress Multisite blog ID of the shop where the origin/main product is located.</p>
<p><strong>Example</strong><br />
The following example increases the child product price by 10%:</p>
<pre class="brush: php; title: ; notranslate">
    add_filter( &#039;woogc/ps/synchronize_product/child_product&#039;, &#039;custom_modify_child_product&#039;, 10, 3 );
    function custom_modify_child_product( $child_product, $main_product_data, $origin_product_blog_ID ) {
        $regular_price = $child_product-&gt;get_regular_price( &#039;edit&#039; );

        if ( &#039;&#039; !== $regular_price ) {
            $child_product-&gt;set_regular_price( wc_format_decimal( (float) $regular_price * 1.10 ) );
        }

        $sale_price = $child_product-&gt;get_sale_price( &#039;edit&#039; );

        if ( &#039;&#039; !== $sale_price ) {
            $child_product-&gt;set_sale_price( wc_format_decimal( (float) $sale_price * 1.10 ) );
        }

        return $child_product;
    }
</pre>
<p>The modified <code>$child_product</code> object must always be returned so that WooCommerce Global Cart can continue the synchronization process.</p>
<p><strong>Modify Different Product Properties</strong></p>
<p>Because the filter provides the actual <code>WC_Product</code> object, standard WooCommerce product methods can be used to modify its properties.</p>
<p>For example, the following changes the product status and adds a custom metadata field:</p>
<pre class="brush: php; title: ; notranslate">
add_filter( &#039;woogc/ps/synchronize_product/child_product&#039;, &#039;customize_child_product&#039;, 10, 3 );

function customize_child_product( $child_product, $main_product_data, $origin_product_blog_ID ) {

    $child_product-&gt;set_status( &#039;draft&#039; );

    $child_product-&gt;update_meta_data(
        &#039;_my_custom_value&#039;,
        &#039;This value is specific to the child shop&#039;
    );

    return $child_product;
}
</pre>
<p>This approach is useful when a destination shop needs to have slightly different product information from the origin shop.</p>
<p>&nbsp;</p>
<p><strong>Working With Custom Taxonomies or Metadata</strong></p>
<p>The filter can also be used when additional data needs to be assigned to the child product that is not handled by the standard synchronization process.</p>
<p>For example:</p>
<pre class="brush: php; title: ; notranslate">
add_filter( &#039;woogc/ps/synchronize_product/child_product&#039;, &#039;custom_child_product_data&#039;, 10, 3 );

function custom_child_product_data( $child_product, $main_product_data, $origin_product_blog_ID ) {

    $child_product-&gt;update_meta_data(
        &#039;_my_custom_field&#039;,
        &#039;Custom value&#039;
    );

    return $child_product;
}
</pre>
<p>For custom taxonomy synchronization, the filter can also be used to retrieve the required taxonomy information from the origin shop and assign it to the synchronized child product.</p>
<p><strong>Important</strong></p>
<p>This filter operates on the <strong>child product object</strong>. It should therefore be used when the objective is to modify the product being created or updated on the destination shop.</p>
<p>When you need to prevent a particular metadata field or property from being synchronized altogether, use the <code><a href="https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-ignore_meta_key/">woogc/ps/synchronize_product/ignore_meta_key</a></code> filter instead.</p>
<p>When you need to execute custom logic for individual synchronized product properties, the <code>woogc/ps/synchronize_product/synchronize_product_data</code> action may be more appropriate.</p>
<p>The <code>$child_product</code> object should be returned from the filter even when no changes are made:</p>
<pre><code>return $child_product;</code></pre>
<p>This filter is particularly useful for networks where the same product is shared between multiple WooCommerce shops but certain product properties, metadata, pricing rules, or other destination-specific information need to be customized.</p>
<p>Custom code using this filter can be placed in the active theme&#8217;s <code>functions.php</code> file or, preferably, in a custom file within:</p>
<pre><code>/wp-content/mu-plugins/</code></pre>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-child_product/">woogc/ps/synchronize_product/child_product</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-child_product/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>woogc/ps/synchronize_product/ignore_meta_key</title>
		<link>https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-ignore_meta_key/</link>
					<comments>https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-ignore_meta_key/#respond</comments>
		
		<dc:creator><![CDATA[admin-woogc]]></dc:creator>
		<pubDate>Thu, 10 Sep 2026 08:15:14 +0000</pubDate>
				<guid isPermaLink="false">https://single-site.wpglobalcart.com/?post_type=documentation&#038;p=16206</guid>

					<description><![CDATA[<p>Name: woogc/ps/synchronize_product/ignore_meta_key Type: Filter Arguments: $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID Filter being used to exclude specific properties, meta keys, or core post fields from being applied to a child product during the product synchronization process. By default, the synchronization routine applies every property and...</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-ignore_meta_key/">woogc/ps/synchronize_product/ignore_meta_key</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Name</strong>: woogc/ps/synchronize_product/ignore_meta_key<br />
<strong>Type:</strong> Filter<br />
<strong>Arguments:</strong> $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID</p>
<p>Filter being used to exclude specific properties, meta keys, or core post fields from being applied to a child product during the product synchronization process.</p>
<p>By default, the synchronization routine applies every property and meta key found on the remote (main) product object onto the local child product. To prevent one or more of these fields from being overwritten on the child &#8212; for example, to preserve a locally customized SEO description, or to stop a child product&#8217;s stock status from being overridden &#8212; a callback can be registered through the &#8216;woogc/ps/synchronize_product/ignore_meta_key&#8217; filter, returning <strong>TRUE</strong> for any key that should be skipped. The following sample code snippets demonstrate common scenarios, including skipping a single meta key, skipping the core <strong>post_title</strong>, <strong>post_status</strong>, <strong>post_content</strong> and <strong>post_excerpt</strong> fields, and applying conditional logic based on the origin blog or the child product&#8217;s current state.</p>
<p>Sample Usage</p>
<p>Skip syncing a specific meta key entirely:</p>
<pre class="brush: php; title: ; notranslate">
add_filter(&#039;woogc/ps/synchronize_product/ignore_meta_key&#039;, &#039;my_woogc_ignore_seo_metadesc&#039;, 10, 6);
function my_woogc_ignore_seo_metadesc( $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID )
    {
        if ( &#039;_yoast_wpseo_metadesc&#039; === $prop_title )
            return TRUE;

        return $ignore;
    }
</pre>
<p>Skip syncing the product name/title:</p>
<pre class="brush: php; title: ; notranslate">
add_filter(&#039;woogc/ps/synchronize_product/ignore_meta_key&#039;, &#039;my_woogc_ignore_product_title&#039;, 10, 6);
function my_woogc_ignore_product_title( $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID )
    {
        if ( &#039;post_title&#039; === $prop_title )
            return TRUE;

        return $ignore;
    }
</pre>
<p>Skip syncing status and short description together:</p>
<pre class="brush: php; title: ; notranslate">
add_filter(&#039;woogc/ps/synchronize_product/ignore_meta_key&#039;, &#039;my_woogc_ignore_status_and_excerpt&#039;, 10, 6);
function my_woogc_ignore_status_and_excerpt( $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID )
    {
        $ignored_fields = array( &#039;post_status&#039;, &#039;post_excerpt&#039; );

        if ( in_array( $prop_title, $ignored_fields, TRUE ) )
            return TRUE;

        return $ignore;
    }
</pre>
<p>Conditionally ignore, based on which blog the data originated from:</p>
<pre class="brush: php; title: ; notranslate">
add_filter(&#039;woogc/ps/synchronize_product/ignore_meta_key&#039;, &#039;my_woogc_ignore_price_unless_blog_three&#039;, 10, 6);
function my_woogc_ignore_price_unless_blog_three( $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID )
    {
        $price_keys = array( &#039;_price&#039;, &#039;_regular_price&#039;, &#039;_sale_price&#039; );

        if ( in_array( $prop_title, $price_keys, TRUE ) &amp;&amp; $origin_product_blog_ID !== 3 )
            return TRUE;

        return $ignore;
    }
</pre>
<p>Inspect $child_product before deciding:</p>
<pre class="brush: php; title: ; notranslate">
add_filter(&#039;woogc/ps/synchronize_product/ignore_meta_key&#039;, &#039;my_woogc_preserve_outofstock_status&#039;, 10, 6);
function my_woogc_preserve_outofstock_status( $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID )
    {
        if ( &#039;_stock_status&#039; === $prop_title &amp;&amp; $child_product-&gt;get_stock_status() === &#039;outofstock&#039; )
            return TRUE;

        return $ignore;
    }
</pre>
<p>Using a class method instead of a standalone function:</p>
<pre class="brush: php; title: ; notranslate">
class My_Woogc_Sync_Customizations {

    public function __construct() {
        add_filter( &#039;woogc/ps/synchronize_product/ignore_meta_key&#039;, array( $this, &#039;ignore_product_title&#039; ), 10, 6 );
    }

    public function ignore_product_title( $ignore, $prop_title, $value, $child_product, $main_product_data, $origin_product_blog_ID ) {

        if ( &#039;post_title&#039; === $prop_title )
            return TRUE;

        return $ignore;
    }
}

new My_Woogc_Sync_Customizations();
</pre>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-ignore_meta_key/">woogc/ps/synchronize_product/ignore_meta_key</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://single-site.wpglobalcart.com/documentation/woogc-ps-synchronize_product-ignore_meta_key/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>woogc/sync/on_post_vars</title>
		<link>https://single-site.wpglobalcart.com/documentation/woogc-sync-on_post_vars/</link>
					<comments>https://single-site.wpglobalcart.com/documentation/woogc-sync-on_post_vars/#respond</comments>
		
		<dc:creator><![CDATA[admin-woogc]]></dc:creator>
		<pubDate>Tue, 19 Sep 2023 15:30:06 +0000</pubDate>
				<guid isPermaLink="false">https://single-site.wpglobalcart.com/?post_type=documentation&#038;p=14112</guid>

					<description><![CDATA[<p>Name: woogc/sync/on_post_vars Type: Filter Arguments: $PostVars Filter being used to acknowledge the plugin engine to proceed with synchronization, usually following a custom AJAX call which is not being recognized as a WooCommerce default. (e.g. wc-ajax=add_to_cart,  wc-ajax=get_refreshed_fragments) Certain plugins and themes use their own methods to handle the...</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-sync-on_post_vars/">woogc/sync/on_post_vars</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Name</strong>: woogc/sync/on_post_vars<br />
<strong>Type:</strong> Filter<br />
<strong>Arguments:</strong> $PostVars</p>
<p>Filter being used to acknowledge the plugin engine to proceed with synchronization, usually following a custom AJAX call which is not being recognized as a WooCommerce default. (e.g. wc-ajax=add_to_cart,  wc-ajax=get_refreshed_fragments)</p>
<p>Certain plugins and themes use their own methods to handle the cart operations like add, remove.  To create a compatibility between such code and the WooCommerce Global Cart plugin, at least a POST parameter must be registered through the &#8216;woogc/sync/on_post_vars&#8217; filter, recommended to be a unique field. The following sample code, inform the plugin engine to trigger a synchronization procedure right after a POST call has completed and included a field <strong>action </strong>=&gt;<strong> woocommerce_add_to_cart_variable_rc</strong></p>
<p>Sample Usage</p>
<pre class="brush: php; title: ; notranslate">
add_filter('woogc/sync/on_post_vars', 'woogc_sync_on_post_vars');
function woogc_sync_on_post_vars( $PostVars )
    {
        $PostVars&#x5B;] = 'action=add_to_cart';
        $PostVars&#x5B;] = 'action=woocommerce_add_to_cart_variable_rc';
        $PostVars&#x5B;] = 'action=product_remove';

        return $PostVars ;
    }
</pre>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-sync-on_post_vars/">woogc/sync/on_post_vars</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://single-site.wpglobalcart.com/documentation/woogc-sync-on_post_vars/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>woogc/disable_global_cart</title>
		<link>https://single-site.wpglobalcart.com/documentation/woogc-disable_global_cart/</link>
					<comments>https://single-site.wpglobalcart.com/documentation/woogc-disable_global_cart/#respond</comments>
		
		<dc:creator><![CDATA[admin-woogc]]></dc:creator>
		<pubDate>Tue, 19 Sep 2023 15:25:16 +0000</pubDate>
				<guid isPermaLink="false">https://single-site.wpglobalcart.com/?post_type=documentation&#038;p=14111</guid>

					<description><![CDATA[<p>Name: woogc/disable_global_cart Type: Filter Arguments: $is_disabled The filter is being used to disable the Global Cart functionality. add_filter( 'woogc/disable_global_cart', 'WooGC_Disable_GlobalCart', 10, 2 ); function WooGC_Disable_GlobalCart ( $status, $_blog_id = '' ) { return TRUE; } The code should be placed inside a php file on wp-content/mu-plugins folder.</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-disable_global_cart/">woogc/disable_global_cart</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>Name:</strong> woogc/disable_global_cart<br />
<strong>Type:</strong> Filter<br />
<strong>Arguments:</strong> $is_disabled</p>
<p>The filter is being used to disable the Global Cart functionality. </p>
<pre class="brush: php; title: ; notranslate">

    add_filter( 'woogc/disable_global_cart',     'WooGC_Disable_GlobalCart', 10, 2 );
    function  WooGC_Disable_GlobalCart ( $status, $_blog_id = '' )
        {
            
            return TRUE;   
        }

</pre>
<p>The code should be placed inside a php file on wp-content/mu-plugins folder.</p>
<p>The post <a href="https://single-site.wpglobalcart.com/documentation/woogc-disable_global_cart/">woogc/disable_global_cart</a> appeared first on <a href="https://single-site.wpglobalcart.com">WooCommerce Global Cart - Single Site</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://single-site.wpglobalcart.com/documentation/woogc-disable_global_cart/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
