{"id":18634963,"date":"2025-09-09T20:44:11","date_gmt":"2025-09-09T20:44:11","guid":{"rendered":"https:\/\/wordpress.org\/support\/?post_type=topic&#038;p=18634963"},"modified":"2025-09-09T22:05:39","modified_gmt":"2025-09-09T22:05:39","slug":"woocommerce-version-10-1-2-delete-meta-tags-for-our-own-good","status":"publish","type":"topic","link":"https:\/\/wordpress.org\/support\/topic\/woocommerce-version-10-1-2-delete-meta-tags-for-our-own-good\/","title":{"rendered":"Woocommerce Version 10.1.2 delete meta tags for our own good"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">We have a WP site where some User content is updated from an external data source. <\/p>\n\n\n\n<ul>\n<li>It is not a CRON job that connects to a remote data source, queries for data, or calls an API to digest data, and then logs into WP to use WP functions to update\/insert User meta data.<\/li>\n\n\n\n<li>The external data source connects directly with the WP database and updates User data and User meta data.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A few months into our process, we ran into an issue with disappearing User meta tags.  Some of the User meta tags that were added for Users were disappearing apparently for random Users. They were disappearing because Woocommerce was deleting them. Again not for all Users, just some, as well as not all custom Meta tags, just some.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It may have started with Woocommerce Version 10.1.2, or perhaps the version before it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WooCommerce <strong>gets all current meta<\/strong> for the customer, compares it to what&#8217;s in its memory (<code>WC_Customer<\/code> object), and <strong>deletes any meta not present in the in-memory object<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In other words, the Woocommerce plugin, at checkout, when it executes WC_Customer-&gt;save(), will delete any User Meta tags it does not think should belong to the User. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is an inconvenient non-documented feature if you know what I mean. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>\/wp-content\/plugins\/woocommerce\/includes\/data-stores\/class-wc-data-store-wp.php:132<br \/>\u2192 delete_metadata_by_mid()<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The function delete_metadata_by_mid() is deleting meta rows <strong>by meta ID<\/strong>, not by meta key, and therefore bypasses ALL standard WP protections. (&#8220;is_protected_meta()&#8221;, &#8220;register_protected_user_meta()&#8221;, &#8220;pre_delete_user_meta&#8221;, etc.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So, if you have any User meta tags that randomly &#8216;disappear&#8217; and you have the Woocommerce plugin, put in a hook with a backtrace and you might be able to determine if it is Woocommerce doing it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function log_user_meta_deletion($meta_ids, $user_id, $meta_key, $meta_value) {<br \/>    $time = current_time('mysql');<br \/>$log_message = sprintf(<br \/>    \"&#091;%s] User ID: %d - Meta Key DELETED: %s - Deleted Value: %s\\n\",<br \/>    $time,<br \/>    $user_id,<br \/>    $meta_key,<br \/>    maybe_serialize($meta_value)<br \/>);<br \/><br \/>$log_file = WP_CONTENT_DIR . '\/uploads\/user-meta-updates.log';<br \/><br \/>error_log($log_message, 3, $log_file);<br \/><br \/>\/\/ stack trace when custom meta tags are being deleted<br \/>foreach ($meta_ids as $meta_id) {<br \/>    $meta = get_metadata_by_mid( 'user', $meta_id );<br \/>    if (in_array($meta-&gt;meta_key, &#091;'MyMissingMetaKey'])) {<br \/>        $log_file = WP_CONTENT_DIR . '\/uploads\/user-meta-updates.log';<br \/><br \/>        error_log(\"Deleted meta key: {$meta-&gt;meta_key} for user $user_id\", 3, $log_file);<br \/>        error_log(\"Backtrace:\\n\" . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true), 3, $log_file);<br \/>    }<br \/>}<br \/>}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The only way that I found to make sure Woocommerce does not delete meta data records from wp_usermeta that are not added using standard WP methods, is to make force them to be added to the Woocommerce customer object. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ add custom meta keys to woocommerce<br \/>add_action( 'woocommerce_before_checkout_process', function() {<br \/>if ( ! is_user_logged_in() ) {<br \/>return;<br \/>}<br \/>    $user_id = get_current_user_id();<br \/>    $customer = new WC_Customer( $user_id );<br \/><br \/>    $custom_keys = &#091;<br \/>        'MyMissingMetaKey1',<br \/>        'MyMissingMetaKey2',<br \/>        'MyMissingMetaKey3',<br \/>        'MyMissingMetaKey4', <br \/>    ];<br \/><br \/>    foreach ( $custom_keys as $key ) {<br \/>        $value = get_user_meta( $user_id, $key, true );<br \/>        $customer-&gt;update_meta_data( $key, $value );<br \/>    }<br \/><br \/>    \/\/ Save manually so WooCommerce doesn't delete meta when updating WC Customer Object<br \/>    $customer-&gt;save();<br \/>}, 5 );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">At the time of posting this, we are no longer losing user meta data. <\/p>\n","protected":false},"template":"","class_list":["post-18634963","topic","type-topic","status-publish","hentry","topic-tag-metadata"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/18634963","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic"}],"about":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":1,"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/18634963\/revisions"}],"predecessor-version":[{"id":18635038,"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/18634963\/revisions\/18635038"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/media?parent=18634963"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}