It is possible to register custom taxonomy in wordpress programmatically by utilizing the register_taxonomy() function, it can be done from widgets, theme or plugins.

The key is to invoke the function in wordpress init hook, so it the custom taxonomy will be registered before other function that may call or use it later on.

Sample of hooking into wordpress init hook :

<?php 

// Hooking into wordpress init hook using normal function
add_action('init', 'my_custom_function');

function my_custom_function() {
  // Perform some action here
}


// Hooking into wordpress init hook using function inside a class
add_action('init', array('sampleClass', 'my_custom_function'));

class sampleClass {
  public function my_custom_function() {
    // Perform some action here
  }
}

?>

After we understand that we should call the custom taxonomy register function inside the init hook, we can create such function as below to register our custom taxonomy programmatically.

 

<?php
// Hooking into init hook
add_action('init', array('registerTaxonomy', 'init'));

class registerTaxonomy {
  
  public function init() {
    // Registering custom taxonomy called location
    $labels = array(
      'name'              => _x('Locations', 'taxonomy general name'),
      'singular_name'     => _x('Location', 'taxonomy singular name'),
      'search_items'      => __('Search Locations'),
      'all_items'         => __('All Locations'),
      'parent_item'       => __('Parent Location'),
      'parent_item_colon' => __('Parent Location:'),
      'edit_item'         => __('Edit Location'),
      'update_item'       => __('Update Location'),
      'add_new_item'      => __('Add New Location'),
      'new_item_name'     => __('New State Location'),
      'menu_name'         => __('Location'),
    );

    $args = array(
      'public' => false,
      'show_ui' => true,
      'show_in_nav_menus' => false,
      'show_tagcloud' => false,
      'show_admin_column' => false,
      'hierarchical' => true,
      'labels' => $labels,
      'capabilities' => array(
        'manage_terms' => 'manage_property_categories',
        'edit_terms' => 'manage_property_categories',
        'delete_terms' => 'manage_property_categories',
        'assign_terms' => 'assign_property_categories',
      ),
    );
    
    // Registering location taxonomy to post_type post
    register_taxonomy('location', 'post', $args);

  }
}

?>

The snippet above will register a custom taxonomy called location and bind the taxonomy to the post post_type.