Recently, I had to create a sync function that would run whenever a WooCommerce product was added to, changed, or saved in the admin. Strangely, the documentation doesn’t provide a hook related to WooCommerce. We should be able to utilize the save post $post type action as WooCommerce products are a custom post type for WordPress. I attempted the following:

add_action('save_post_product', 'mp_sync_on_product_save', 10, 3);
function mp_sync_on_product_save( $post_id, $post, $update ) {
    $product = wc_get_product( $post_id );
    // do something with this product
}

I discovered that the retrieved product contains data from before the most recent updates were made. But how can the hook execute after the post has been saved to the database? Then it dawned on me: the majority of WooCommerce product data is kept in post meta. The save post hook is also executed before the post meta is changed. As a result, we must utilize a hook that fires when the post meta is modified or added. In our scenario, we need to hook on two different actions (added post meta, when the product post meta is added, and updated post meta, when it is updated). We also prefer added post meta over add post meta since it runs after the modifications are saved to the database.

When any post meta is altered, the post meta hooks trigger, which implies we need to check a few things:

  • If several product fields have been modified, the hook will be invoked for each. Fortunately, there is a meta key called ‘_edit lock’ that is always set while editing a post, so we can activate our function when this is set.
  • We must also ensure that we are dealing with a product post_type.

When we put all of this together, we have our updated hook, which executes when all of the WooCommerce product data is saved to the database:

add_action( 'added_post_meta', 'mp_sync_on_product_save', 10, 4 );
add_action( 'updated_post_meta', 'mp_sync_on_product_save', 10, 4 );
function mp_sync_on_product_save( $meta_id, $post_id, $meta_key, $meta_value ) {
    if ( $meta_key == '_edit_lock' ) { // we've been editing the post
        if ( get_post_type( $post_id ) == 'product' ) { // we've been editing a product
            $product = wc_get_product( $post_id );
            // do something with this product
        }
    }
}

WooCommerce 3.x technique has been updated.

WooCommerce 3.0 has hooks that execute when a product is modified (woocommerce update product) or created (woocommerce new product). This enables us to use a much simpler code that does not need us to verify whether a product is being updated or whether the _edit lock flag is set:

add_action( 'woocommerce_new_product', 'mp_sync_on_product_save', 10, 1 );
add_action( 'woocommerce_update_product', 'mp_sync_on_product_save', 10, 1 );
function mp_sync_on_product_save( $product_id ) {
     $product = wc_get_product( $product_id );
     // do something with this product
}

Categorized in: