Last updated: 31st October 2024
TABLE OF CONTENTS
- 1. Preamble
- 2. WooCommerce Analytics reports - Troubleshooting
- 3. Cleanup the duplicate data
- 4. Contact us if you have any questions
1. Preamble
Between the 25th and the 26th of October 2024, we received reports that the WooCommerce Analytics started showing much higher revenue figures than usual. Apparently, the reports started counting the same orders multiple times, and the reason seems to be the presence of duplicate data.
The root cause of the issue seems to be a glitch that occurs in the WooCommerce core when the Currency Switcher saves against an order the exchange rate used to calculate the analytics in the shop's base currency. In version 5.2.0.241007 of our solution, we made a minor change to the logic that occurs when an order is saved, or created. In simple terms, the logic can be described as
- Update custom order meta A (e.g. the order total in base currency).
- Update custom order meta B (e.g. the order tax total in base currency) .
- Update custom order meta C (e.g. other meta in base currency).
- Etc.
- Update base currency exchange rate.
The exchange rate to be saved at step #5 was calculated at every step, but it was always the same. Due to that, we optimised the logic as follows:
- Update base currency exchange rate.
- Update custom order meta A (e.g. the order total in base currency).
- Update custom order meta B (e.g. the order tax total in base currency) .
- Update custom order meta C (e.g. other meta in base currency).
- Etc.
All these calls are made via the libraries provided by WooCommerce, which are responsible for adding the meta when it's missing, and updating it when it's present. This works fine, but, for some reason, our minor change causes WooCommerce to "miss" the exchange rate saved against the order after it has been set. When that happens, WooCommerce ends up adding the custom meta twice, instead of updating it.
This looks like an edge condition, which doesn't seem to occur on every site, which is why we didn't post it during our regular testing. As of the 31st October 2024, we haven't been able to isolate the exact element that causes . It seems to be connected to the presence of specific plugins that perform their operations during the order creations, but we don't have a conclusive answer. While we keep looking for the root cause, we've implemented a safeguard in version 5.2.3.241101 of the Currency Switcher, which prevents the issue from occurring.
While we gather more information about the glitch, you can perform the following operations:
- Update the Currency Switcher to version 5.2.3.241101. This will prevent the duplication of further duplicates.
- Follow the instructions below to find and remove the duplicate data.
2. WooCommerce Analytics reports - Troubleshooting
100 USD + 100 EUR + 100 GBP = 300 USD
100 USD + (100 EUR x <exchange rate to USD>) + (100 GBP x <exchange rate to USD>) = 337.81 USD
Order ID | Total | Exchange rate |
1 | 100 | 0.4278356 |
2 | 120 | 0.4278356 |
3 | 130 | 0.4278356 |
Order ID | Total | Exchange rate |
1 | 100 | 0.4278356 |
1 | 100 | 0.4278356 |
1 | 100 | 0.4278356 |
2 | 120 | 0.4278356 |
3 | 130 | 0.4278356 |
1.1 How to find the duplicate data
1.1.1 With the HPOS feature enabled
# Change the "wp_" table prefix to the correct one SELECT WCOM.order_id ,COUNT(WCOM.meta_value) AS base_currency_exchange_rate_count FROM wp_wc_orders_meta WCOM WHERE (WCOM.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM.order_id ORDER BY WCOM.order_id
1.1.2 With the HPOS feature disabled (legacy order tables)
# Change the "wp_" table prefix to the correct one SELECT WCOM.post_id ,COUNT(WCOM.meta_value) AS base_currency_exchange_rate_count FROM wp_postmeta WCOM WHERE (WCOM.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM.post_id ORDER BY WCOM.post_id
order_id | base_currency_exchange_rate_count |
1 | 3 |
2 | 1 |
3 | 1 |
1.2 View the duplicate data
1.2.1 With the HPOS feature enabled
# IMPORTANT! Change the "wp_" table prefix to the correct one before running the query SELECT WCOM1.order_id ,WCOM1.meta_value AS base_currency_exchange_rate ,orders_with_duplicate_data.base_currency_exchange_rate_count FROM wp_wc_orders_meta WCOM1 JOIN ( # Change the "wp_" table prefix to the correct one SELECT WCOM.order_id, COUNT(WCOM.meta_value) AS base_currency_exchange_rate_count FROM wp_wc_orders_meta WCOM WHERE (WCOM.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM.order_id HAVING (base_currency_exchange_rate_count > 1) ) as orders_with_duplicate_data ON (orders_with_duplicate_data.order_id = WCOM1.order_id) WHERE (WCOM1.meta_key = '_base_currency_exchange_rate')
1.2.2 With the HPOS feature disabled (legacy order tables)
# Change the "wp_" table prefix to the correct one SELECT WCOM1.post_id ,WCOM1.meta_value AS base_currency_exchange_rate ,orders_with_duplicate_data.base_currency_exchange_rate_count FROM wp_postmeta WCOM1 JOIN ( # Change the "wp_" table prefix to the correct one SELECT WCOM.post_id AS order_id, COUNT(WCOM.meta_value) AS base_currency_exchange_rate_count FROM wp_postmeta WCOM WHERE (WCOM.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM.post_id HAVING (base_currency_exchange_rate_count > 1) ) as orders_with_duplicate_data ON (orders_with_duplicate_data.order_id = WCOM1.post_id) WHERE (WCOM1.meta_key = '_base_currency_exchange_rate')
3. Cleanup the duplicate data
If your database contains duplicate data, you can use the following queries to delete the duplicates, keeping only one entry per order.
# Change the "wp_" table prefix to the correct one before running the query DELETE wp_wc_orders_meta FROM wp_wc_orders_meta JOIN ( -- Return the duplicate with the lowest ID. Since there are always two, we can -- delete either one SELECT WCOM1.order_id ,MIN(WCOM1.id) AS base_currency_exchange_rate_id FROM wp_wc_orders_meta WCOM1 JOIN ( -- Find all the duplicates of the the _base_currency_exchange_rate meta SELECT WCOM.order_id, COUNT(WCOM.meta_value) AS base_currency_exchange_rate_count FROM wp_wc_orders_meta WCOM WHERE (WCOM.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM.order_id HAVING (base_currency_exchange_rate_count > 1) ) as orders_with_duplicate_data ON (orders_with_duplicate_data.order_id = WCOM1.order_id) WHERE (WCOM1.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM1.order_id ) AS entries_to_delete ON (entries_to_delete.base_currency_exchange_rate_id = wp_wc_orders_meta.id);
# IMPORTANT! Change the "wp_" table prefix to the correct one before running the query DELETE wp_postmeta FROM wp_postmeta JOIN ( -- Return the duplicate with the lowest ID. Since there are always two, we can -- delete either one SELECT WCOM1.post_id ,MIN(WCOM1.meta_id) AS base_currency_exchange_rate_id FROM wp_postmeta WCOM1 JOIN ( -- Find all the duplicates of the the _base_currency_exchange_rate meta SELECT WCOM.post_id, COUNT(WCOM.meta_value) AS base_currency_exchange_rate_count FROM wp_postmeta WCOM WHERE (WCOM.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM.post_id HAVING (base_currency_exchange_rate_count > 1) ) as orders_with_duplicate_data ON (orders_with_duplicate_data.post_id = WCOM1.post_id) WHERE (WCOM1.meta_key = '_base_currency_exchange_rate') GROUP BY WCOM1.post_id ) AS entries_to_delete ON (entries_to_delete.base_currency_exchange_rate_id = wp_postmeta.meta_id);
4. Contact us if you have any questions
If you have any questions about the cleanup of the duplicate data, or if you need help with the troubleshooting, please feel free to contact us: https://aelia.co/contact. We will be happy to assist you.