I have a website with products (shoes), i have some shoes models registered as taxonomy on the function.php file like so:

function add_custom_taxonomies() {

    register_taxonomy('mod-nike', 'pompitup_product', array(
    // Hierarchical taxonomy (like categories)
    'hierarchical' => false,
    // This array of options controls the labels displayed in the WordPress Admin UI
    'labels' => array(
        'name' => _x( 'modeles Nike', 'taxonomy general name' ),
        'menu_name' => __( 'Modeles Nike' ),

add_action( 'init', 'add_custom_taxonomies', 0 );

this is working as it should.

my problem is that i have a few custom taxonomies created this way but the user should be able to add more on the backend, with the help of an option page.

so i tried to hook on "acf/save_post" like so:

function my_acf_save_post( $post_id ){
//some logic that take have to do with custom post....

    function register_brand_tax(){

    $brand_to_add = get_field_object('field_52d6f9449e688', 'option');
    //in the variable $brand_to_add I get the field object from the option pages

    if( !empty($brand_to_add['value'])){

        //then I instert the term on the "brand category" (this works when outisde of a function)
            $brand_to_add['value'], // the term 
            'marque' //the tax

        register_taxonomy('mod-' . $brand_to_add['value'], 'pompitup_product', 
            'hierarchical' => false,
            'labels' => array(
                   'name' => _x( 'modeles ' . $brand_to_add['value'], 'taxonomy general name' ),
                    'menu_name' => __( 'Modeles ' . $brand_to_add['value'] ),

add_action( 'init', 'register_brand_tax', 20 );
add_action('acf/save_post', 'my_acf_save_post', 1); 

the wp_insert_term is working but apparently the register_taxonomy must be called by an 'init' action that's why i tried to call it inside of the 'acf/save_post' but diden't had any luck so far, is there any way even outside of ACF to let my user register a new taxonomy from the admin backend?


Consider instead a single, hierarchical taxonomy, where the top level terms are brands such as Nike/Adidas/etc, and child terms are models.

Otherwise you face a scaling issue, as the number of brands increases, so do the number of taxonomies, and so does the complexity of the code behind the scenes.


Here is how i didi it in the end :

First the option page (from that page the user can see all the brands and add new ones).

The new brand fields is set to '' (empty) when it is loaded.

// Reset new brand field
add_filter('acf/load_field/key=field_52d6f9449e688', 'reset_new_brand');

 function reset_new_brand( $field )
        // reset choices
        $field['value'] = '';

        // Important: return the field
        return $field;

When the option page is saved a new category is created

// run AFTER ACF saves the $_POST['fields'] data
add_action('acf/save_post', 'my_acf_save_option_page', 20); 

function my_acf_save_option_page( $post_id ){

        $brand_to_add = get_field_object('field_52d6f9449e688', 'option');

        if( !empty($brand_to_add['value'])){

                wp_insert_term( $brand_to_add['value'], 'marque' );
                //delete_option('marque_children'); // clear the cache

             }//end option page stuff

when editing a post all the brands are loaded from the category

    // Load Brand on edit product
    add_filter('acf/load_field/key=field_52b2c7c6bc3e5', 'load_marque_field');

 function load_marque_field( $field )
        // reset choices
        $field['choices'] = array();

        // get the textarea value from options page without any formatting
            $choices = get_terms('marque', array('parent' => 0, 'hide_empty' => false, 'orderby'=> 'name' ));

            $arr = array();
        // loop through array and add to field 'choices'            
            foreach( $choices as $tax_term ) {
                $arr[$tax_term->slug] = $tax_term->name;

            $field['choices'] = $arr;

        // Important: return the field
        return $field;

when editing or creating a post there is a Advenced custom field called "new model" if this field is set then when the post is saved / updated à new child category is created on the selected brand. when saving the post I also check if any child categories have a count of 0 they are deleted.

// run BEFORE ACF saves the $_POST['fields'] data
add_action('acf/save_post', 'my_acf_save_post', 1); 

//Register terms from new model field and category form brand
function my_acf_save_post( $post_id ){
    // vars
    $fields = false;

 if(get_post_type( $post_id ) === "pompitup_product"){
    // load from post
    if( isset($_POST['fields']) ){
        $fields = $_POST['fields'];
        $selected_brand = $fields[field_52b2c7c6bc3e5];
        $new_tax_field = $fields[field_52c53c86e1fb2];
        $existing_tax_field = $fields[field_52dbf2af72c54];         

            if( isset($new_tax_field)){

                $new_tax = $new_tax_field;              

                update_field('field_52dbf2af72c54', $new_tax, $post_id);

                //check if the term exist in selected brand
                $term = term_exists($new_tax, $selected_brand);
                if ($term == 0 ) {
                //get selected brand infos (id)
                $getTermOptions = get_term_by('slug', $selected_brand, 'marque');

                //insert new term in selected brand

                wp_insert_term( $new_tax, 'marque', array( 'parent'=> (int)$getTermOptions->term_id ) );
                delete_option('marque_children'); // clear the cache



                if( isset($existing_tax_field)){ $new_tax = $existing_tax_field; }  


            //set category (brand)
            wp_set_object_terms( $post_id, $selected_brand, 'marque', false );

            //set category model
            wp_set_object_terms( $post_id, $new_tax, 'marque', true );

            //delet emtpy tax
            $taxonomyName = "marque";

            //This gets top layer terms only.  This is done by setting parent to 0.  
            $parent_terms = get_terms($taxonomyName, array('parent' => 0, 'hide_empty' => false));   
            foreach ($parent_terms as $pterm) {
                //Get the Child terms
                $terms = get_terms($taxonomyName, array('parent' => $pterm->term_id, 'hide_empty' => false));
                foreach ($terms as $term) {

                     if( 0 == $term->count ){
                          wp_delete_term( $term->term_id, $term->taxonomy);


        }//end isset($_POST['fields'])---->for post
    }//end check if post-type== pompitup_product

    // ...
}//end my_acf_save_post

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.