31 thoughts on “Programatically Create Woocommerce Products with Variations

    1. the code work fine programmatically. however when we save the post product in admin by clicking update button. All the variation link gone.

  1. Nice post. I added your code into my theme, however when executed it creates a simple product with no variations.

    I´m using the last version of woocommerce.

    What could be wrong?

    1. Did u get it working? If not, is the code you posted the code you are having issues with? Let me know and I'll help if I can.

      1. Hi, thanks for your reply. I got it working.

        The code I posted is the good one 🙂

        That´s a function you can use to create variable products with ease, you just pass the data as parameters. I´m using that function on the website I´m building.

        1. Hello Jose
          this code only works when you have one variant. could you help with how to work with more than one variant ie size and color?. Thanks alot in advance

  2. Hi, i created a function for adding variable products based on your code. I share it here in case anyone needs it:

    The first parameter is the title of the product, $cats is the products category id which has to be an array and must be created previously, $variations is an array which contains the variations with prices, descriptions, discount, and $variations_key is the key of the parent attribute which has to be created previously on teh attributes page.

    I´m creating a ticket´s selling store and I´m using 2 globals: $logger and $vgh from my framework, please ignore them.

    function create_variable_woo_product($title, $cats = array(), $variations, $variations_key) {

    global $wpdb, $logger, $vgh;
    $post = array(
    'post_title' => $title,
    'post_status' => "publish",
    'post_name' => sanitize_title($title), //name/slug
    'post_type' => "product"
    );

    //Create product/post:
    $new_prod_id = wp_insert_post($post, $wp_error);
    $logger->info('Crear producto WooCommerce: ID:' . $new_prod_id);

    //make product type be variable:
    wp_set_object_terms($new_prod_id, 'variable', 'product_type');

    //add category to product:
    wp_set_object_terms($new_prod_id, $cats, 'product_cat');

    //################### Add size attributes to main product: ####################
    //Array for setting attributes
    $var_keys = array();
    $total_tickets = 0;
    foreach ($variations as $variation) {
    $total_tickets += (int) $variation["entradas"];
    $var_keys[] = sanitize_title($variation['desc']);
    wp_insert_term(
    $variation['desc'], // the term
    $variations_key, // the taxonomy
    array(
    'slug' => sanitize_title($variation['desc'])
    )
    );
    }
    wp_set_object_terms($new_prod_id, $var_keys, $variations_key );

    $thedata = Array($variations_key => Array(
    'name' => $variations_key,
    'value' => implode( ' | ', $var_keys),
    'is_visible' => '1',
    'is_variation' => '1',
    'is_taxonomy' => '1'
    ));
    update_post_meta($new_prod_id, '_product_attributes', $thedata);
    //########################## Done adding attributes to product #################
    //set product values:
    update_post_meta($new_prod_id, '_stock_status', ( (int) $total_tickets > 0) ? 'instock' : 'outofstock');
    update_post_meta($new_prod_id, '_sku', mt_rand() );
    update_post_meta($new_prod_id, '_stock', $total_tickets);
    update_post_meta($new_prod_id, '_visibility', 'visible');

    update_post_meta($new_prod_id, '_default_attributes', array());

    //###################### Add Variation post types for sizes #############################
    $i = 1;

    $var_prices = array();

    //set IDs for product_variation posts:
    foreach ($variations as $variation) {
    $my_post = array(
    'post_title' => 'Variation #' . $i . ' of ' . count($variations) . ' for product#' . $new_prod_id,
    'post_name' => 'product-' . $new_prod_id . '-variation-' . $i,
    'post_status' => 'publish',
    'post_parent' => $new_prod_id, //post is a child post of product post
    'post_type' => 'product_variation', //set post type to product_variation
    'guid' => home_url() . '/?product_variation=product-' . $new_prod_id . '-variation-' . $i
    );

    //Insert ea. post/variation into database:
    $attID = wp_insert_post($my_post);
    //Create 2xl variation for ea product_variation:
    update_post_meta($attID, 'attribute_' . $variations_key, sanitize_title($variation['desc']));

    update_post_meta($attID, '_sale_price', pyo_get_price($variation));
    update_post_meta($attID, '_regular_price', (int) $variation["cantidad"]);
    $var_prices[ $i - 1]['id'] = $attID;
    $var_prices[$i - 1 ]['regular_price'] = sanitize_title($variation['cantidad']);
    $var_prices[$i - 1 ]['sale_price'] = pyo_get_price($variation);

    //add size attributes to this variation:
    wp_set_object_terms($attID, $var_keys, 'pa_' . sanitize_title($variation['desc']));

    $thedata = Array( $variations_key => Array(
    'name' => $variations_key,
    'value' => sanitize_title($variation['desc']),
    'is_visible' => '1',
    'is_variation' => '1',
    'is_taxonomy' => '1'
    ));
    update_post_meta($attID, '_product_attributes', $thedata);
    update_post_meta($attID, '_sku', mt_rand());
    update_post_meta($attID, '_stock_status', ( (int) $variation["entradas"] > 0) ? 'instock' : 'outofstock');
    update_post_meta($attID, '_manage_stock', 'yes');
    update_post_meta($attID, '_stock', $variation["entradas"]);
    $i++;
    }

    $i = 0;
    foreach ($var_prices as $var_price) {
    $regular_prices[] = $var_price['regular_price'];
    $sale_prices[] = $var_price['sale_price'];
    }
    update_post_meta($new_prod_id, '_min_variation_price', min($sale_prices));
    update_post_meta($new_prod_id, '_max_variation_price', max($sale_prices));
    update_post_meta($new_prod_id, '_min_variation_regular_price', min($regular_prices));
    update_post_meta($new_prod_id, '_max_variation_regular_price', max($regular_prices));

    update_post_meta($new_prod_id, '_min_price_variation_id', $var_prices[array_search(min($sale_prices), $sale_prices)]['id']);
    update_post_meta($new_prod_id, '_max_price_variation_id', $var_prices[array_search(max($sale_prices), $sale_prices)]['id']);
    update_post_meta($new_prod_id, '_min_regular_price_variation_id', $var_prices[array_search(min($regular_prices), $regular_prices)]['id']);
    update_post_meta($new_prod_id, '_max_regular_price_variation_id', $var_prices[array_search(max($regular_prices), $regular_prices)]['id']);
    }

    1. Could you please give me an example of calling above function in functions.php itself like
      add_action( 'template_redirect', 'create_variable_woo_product()' );

  3. Hi i would like to ask you how can i add image for each variation example in variation "2xl' i want to add a different image than the feature.

  4. It's been a while since I coded this, but if I recall correctly, you should be able to simply more than one by adding the image values as a comma separated list instead of a single image and the first will be the featured image while the others will be regular images... Hope that works for you. Good luck!

  5. thank you for you quick answer but i dont mean that i want in $variation_five to add an image . In order to add an image you use that part of code update_post_meta( $new_post_id, '_product_image_gallery', $imgID) ; i suppose that i am going to use the same code with a different tag like _product_image_variation but i dont know the specific tag. can you guide me ?

    Merry Christmas

  6. I have one more question i want to add more attributes like you have xl ,2xl etc i want to add colors but when i clone the rows you insert the attributes it gets only the second attribute and note the first one. Can you help me please?

  7. Never understood why WooCommerce uses update_post_meta() to set meta data on products, shouldn't it be using update_metadata('product', blah, blah)

  8. Hi jafty

    Firstly, I'd like to thank you for putting this up. It has helped me get a sense of direction in terms of how I had to populate woocommerce products with variations. My products have two main variation, schedule and location.

    I've got most of it working, however have got myself in a sticky situation, not being able to get one of variation that was selected earlier not showing on the cart page.

    I have attached the code below.
    Any help would be greatly appreciated.


    <?php

    /**
    * @author BEDRE, Puneeth
    * The first parameter is the title of the product, $cats is the products category id
    * which has to be an array and must be created previously, $variations is an array which
    * contains the variations with prices, descriptions, discount, and $variations_key is
    * the key of the parent attribute which has to be created previously on the attributes page.
    *
    * @param String $title Title of the product to be created
    * @param array $variations An array of key values pairs, locations, schedules and availability
    * @param String $price Price for product listing.
    *
    */

    // Prevent script hijacking
    defined('ABSPATH') or die('No script kiddies please');

    function addProd($title, $variations, $price, $sku) {
    $variances = $variations[0];
    $locations = $variations[1];
    $schedules = $variations[2];

    // print_r($schedules);
    // echo '';
    // print_r($locations);
    // echo '';
    // print_r($variances);
    // echo '';

    $scheduleAttr = wc_attribute_taxonomy_name( 'Schedule' );
    $locationAttr = wc_attribute_taxonomy_name( 'Location' );

    // global wp class, set of functions used to interact with a database
    global $wpdb;

    // array to create new post
    $post = array(
    'post_title' => $title,
    'post_content' => "product post content goes here...",
    'post_status' => "publish",
    'post_excerpt' => "product excerpt content...",
    'post_name' => sanitize_title($title), //name/slug
    'post_type' => "product"
    );

    //Create product/post:
    $new_prod_id = wp_insert_post($post, $wp_error);

    $attributes = array(
    $locationAttr => array(
    "name" => $locationAttr,
    'value'=>implode(' | ', $locations),
    "is_visible" => 1,
    "is_variation" => 1,
    "is_taxonomy" => 1,
    ),
    $scheduleAttr => array(
    "name" => $scheduleAttr,
    'value'=>implode(' | ', $schedules),
    "is_visible" => 1,
    "is_variation" => 1,
    "is_taxonomy" => 1,
    ),
    );

    update_post_meta( $new_prod_id,'_product_attributes',$attributes);

    wp_set_object_terms($new_prod_id, $locations, $locationAttr);
    wp_set_object_terms($new_prod_id, $schedules, $scheduleAttr);

    //make product type be variable:
    wp_set_object_terms($new_prod_id, 'variable', 'product_type', false);

    //set product values:
    update_post_meta( $new_prod_id, '_stock_status', 'instock');
    update_post_meta( $new_prod_id, '_sku', $sku);
    update_post_meta( $new_prod_id, '_visibility', 'visible' );

    $totalvariance = count($variances);
    $count = 0;
    foreach ($variances as $variance) {

    $location = $variance[0];
    $schedule = $variance[1];
    $availability = $variance[2];

    // echo $location;
    // echo '';
    // echo $schedule;
    // echo '';
    // echo $availability;
    // echo '';

    $my_post = array(
    'post_title' => 'Variation #' . $count . ' of ' . $totalvariance,
    'post_name' => 'product-' . $new_prod_id . '-variation-' . $count,
    'post_status' => 'publish',
    'post_parent' => $new_prod_id, //post is a child post of product post
    'post_type' => 'product_variation', //set post type to product_variation
    // 'guid' => home_url() . '/?product_variation=product-' . $new_prod_id . '-variation-' . $count++
    );

    //Insert ea. post/variation into database:
    $attID = wp_insert_post ($my_post );

    update_post_meta($attID, '_price', $price);
    update_post_meta($attID, '_regular_price', $price);
    update_post_meta($attID, '_manage_stock', 'yes');
    update_post_meta($attID, '_stock', $availability);

    update_post_meta( $attID, 'attribute_' . $locationAttr, $location );
    update_post_meta( $attID, 'attribute_' . $scheduleAttr, $schedule );

    WC_Product_Variable::sync( $parent_id );
    }

    }

  9. Hi,
    Thanks for the code.
    I want to create variation for two attributes (Size & color)
    I have followed your code and products & variations are being added but under variations size and color are not being selected.

    Following is the code.

    foreach ($variations as $variation) {
    $my_post = array(
    'post_title' => 'Variation #' . $i . ' of '.$cont.' for prdct#'. $new_post_id,
    'post_name' => 'product-' . $new_post_id . '-variation-' . $i,
    'post_status' => 'publish',
    'post_parent' => $new_post_id,//post is a child post of product post
    'post_type' => 'product_variation',//set post type to product_variation
    'guid' => home_url() . '/?product_variation=product-' . $new_post_id . '-variation-' . $i
    );
    $attID = wp_insert_post( $my_post );

    update_post_meta($attID, 'attribute_pa_color', $variation['color']);
    update_post_meta($attID, 'attribute_pa_size', $variation['size']);

    update_post_meta($attID, '_price', $variation['price']);
    update_post_meta($attID, '_regular_price', $variation['price']);

    update_post_meta($attID, '_sku', $sku.'-'.$variation['color'].'-'.$variation['size']);
    update_post_meta($attID, '_virtual', 'no');
    update_post_meta($attID, '_downloadable', 'no');
    update_post_meta($attID, '_manage_stock', 'no');
    update_post_meta($attID, '_stock_status', 'instock');

    wp_set_object_terms($attID, $color_arr, 'pa_color');
    wp_set_object_terms($attID, $size_arr, 'pa_size');

    $thedata = Array(
    'pa_color' => Array(
    'name' => $variation['color'],
    'value' => '',
    'is_visible' => '1',
    'is_variation' => '1',
    'is_taxonomy' => '1'
    ),
    'pa_size' => Array(
    'name' => $variation['size'],
    'value' => '',
    'is_visible' => '1',
    'is_variation' => '1',
    'is_taxonomy' => '1'
    )
    );
    update_post_meta($attID, '_product_attributes', $thedata);
    }

    Thanks for your help.

  10. Hello,

    This is the great article and solution which I've found on the internet to create variable product programmatically.

    But, I need some suggestion about what I should do change if I've 2 variants like Color and Size. Can you please help me to solve it out.

    Looking forward to your reply.

    Thanks 🙂

  11. Thank you- didn't quite work out for me but this had what I needed to get my project done. Merged standalone products into variations of the same product- couldn't have done it without some of the quirks your script had workarounds for. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *