diff --git src/wp-admin/js/customize-nav-menus.js src/wp-admin/js/customize-nav-menus.js
index 58c27a8..9828e97 100644
--- src/wp-admin/js/customize-nav-menus.js
+++ src/wp-admin/js/customize-nav-menus.js
@@ -1275,7 +1275,7 @@
 			}
 
 			control.params.el_classes = containerClasses.join( ' ' );
-			control.params.item_type_label = api.Menus.getTypeLabel( settingValue.type, settingValue.object );
+			control.params.item_type_label = settingValue.type_label;
 			control.params.item_type = settingValue.type;
 			control.params.url = settingValue.url;
 			control.params.target = settingValue.target;
@@ -2552,36 +2552,6 @@
 	};
 
 	/**
-	 * Given a menu item type & object, get the label associated with it.
-	 *
-	 * @param {string} type
-	 * @param {string} object
-	 * @return {string}
-	 */
-	api.Menus.getTypeLabel = function( type, object ) {
-		var label,
-			data = api.Menus.data;
-
-		if ( 'post_type' === type ) {
-			if ( data.itemTypes.postTypes[ object ] ) {
-				label = data.itemTypes.postTypes[ object ].label;
-			} else {
-				label = data.l10n.postTypeLabel;
-			}
-		} else if ( 'taxonomy' === type ) {
-			if ( data.itemTypes.taxonomies[ object ] ) {
-				label = data.itemTypes.taxonomies[ object ].label;
-			} else {
-				label = data.l10n.taxonomyTermLabel;
-			}
-		} else {
-			label = data.l10n.custom_label;
-		}
-
-		return label;
-	};
-
-	/**
 	 * Given a menu item ID, get the control associated with it.
 	 *
 	 * @param {string} menuItemId
diff --git src/wp-includes/class-wp-customize-control.php src/wp-includes/class-wp-customize-control.php
index cc9469e..03632bd 100644
--- src/wp-includes/class-wp-customize-control.php
+++ src/wp-includes/class-wp-customize-control.php
@@ -1739,7 +1739,7 @@ class WP_Customize_Nav_Menu_Item_Control extends WP_Customize_Control {
 			</p>
 
 			<div class="menu-item-actions description-thin submitbox">
-				<# if ( 'custom' != data.item_type && '' != data.original_title ) { #>
+				<# if ( ( 'post_type' == data.item_type || 'taxonomy' == data.item_type ) && '' != data.original_title ) { #>
 				<p class="link-to-original">
 					<?php printf( __( 'Original: %s' ), '<a class="original-link" href="{{ data.url }}">{{ data.original_title }}</a>' ); ?>
 				</p>
diff --git src/wp-includes/class-wp-customize-nav-menus.php src/wp-includes/class-wp-customize-nav-menus.php
index 502ad2b..3904148 100644
--- src/wp-includes/class-wp-customize-nav-menus.php
+++ src/wp-includes/class-wp-customize-nav-menus.php
@@ -176,6 +176,16 @@ final class WP_Customize_Nav_Menus {
 			}
 		}
 
+		/**
+		 * Filter the available menu items.
+		 *
+		 * @param array  $items    The array of menu items.
+		 * @param string $obj_type The object type.
+		 * @param string $obj_name The object name.
+		 * @param int    $page     The current page number.
+		 */
+		$items = apply_filters( 'customize_nav_menu_available_items', $items, $obj_type, $obj_name, $page );
+
 		return $items;
 	}
 
@@ -596,21 +606,37 @@ final class WP_Customize_Nav_Menus {
 		);
 
 		$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
-		foreach ( $post_types as $slug => $post_type ) {
-			$items['postTypes'][ $slug ] = array(
-				'label' => $post_type->labels->singular_name,
-			);
+		if ( $post_types ) {
+			foreach ( $post_types as $slug => $post_type ) {
+				$items['postTypes'][ $slug ] = array(
+					'title'  => $post_type->labels->singular_name,
+					'object' => 'post_type',
+					'type'   => $post_type->name,
+				);
+			}
 		}
 
 		$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );
-		foreach ( $taxonomies as $slug => $taxonomy ) {
-			if ( 'post_format' === $taxonomy && ! current_theme_supports( 'post-formats' ) ) {
-				continue;
+		if ( $taxonomies ) {
+			foreach ( $taxonomies as $slug => $taxonomy ) {
+				if ( 'post_format' === $taxonomy && ! current_theme_supports( 'post-formats' ) ) {
+					continue;
+				}
+				$items['taxonomies'][ $slug ] = array(
+					'title'  => $taxonomy->labels->singular_name,
+					'object' => 'taxonomy',
+					'type'   => $taxonomy->name,
+				);
 			}
-			$items['taxonomies'][ $slug ] = array(
-				'label' => $taxonomy->labels->singular_name,
-			);
 		}
+
+		/**
+		 * Filter the available menu item types.
+		 *
+		 * @param array $items Custom menu item types.
+		 */
+		$items = apply_filters( 'customize_nav_menu_available_item_types', $items );
+
 		return $items;
 	}
 
@@ -716,32 +742,21 @@ final class WP_Customize_Nav_Menus {
 				</div>
 			</div>
 			<?php
-
-			// @todo: consider using add_meta_box/do_accordion_section and making screen-optional?
 			// Containers for per-post-type item browsing; items added with JS.
-			$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'object' );
-			if ( $post_types ) :
-				foreach ( $post_types as $type ) :
-					?>
-					<div id="available-menu-items-<?php echo esc_attr( $type->name ); ?>" class="accordion-section">
-						<h4 class="accordion-section-title"><?php echo esc_html( $type->label ); ?> <span class="spinner"></span> <span class="no-items"><?php _e( 'No items' ); ?></span> <button type="button" class="not-a-button"><span class="screen-reader-text"><?php _e( 'Toggle' ); ?></span></button></h4>
-						<ul class="accordion-section-content" data-type="<?php echo esc_attr( $type->name ); ?>" data-obj_type="post_type"></ul>
-					</div>
-				<?php
-				endforeach;
-			endif;
+			foreach ( (array) self::available_item_types() as $item_type ) {
+				if ( empty( $item_type ) ) {
+					continue;
+				}
 
-			$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'object' );
-			if ( $taxonomies ) :
-				foreach ( $taxonomies as $tax ) :
+				foreach( $item_type as $item ) {
 					?>
-					<div id="available-menu-items-<?php echo esc_attr( $tax->name ); ?>" class="accordion-section">
-						<h4 class="accordion-section-title"><?php echo esc_html( $tax->label ); ?> <span class="spinner"></span> <span class="no-items"><?php _e( 'No items' ); ?></span> <button type="button" class="not-a-button"><span class="screen-reader-text"><?php _e( 'Toggle' ); ?></span></button></h4>
-						<ul class="accordion-section-content" data-type="<?php echo esc_attr( $tax->name ); ?>" data-obj_type="taxonomy"></ul>
+					<div id="available-menu-items-<?php echo esc_attr( $item['type'] ); ?>" class="accordion-section">
+						<h4 class="accordion-section-title"><?php echo esc_html( $item['title'] ); ?> <span class="no-items"><?php _e( 'No items' ); ?></span><span class="spinner"></span> <button type="button" class="not-a-button"><span class="screen-reader-text"><?php _e( 'Toggle' ); ?></span></button></h4>
+						<ul class="accordion-section-content" data-type="<?php echo esc_attr( $item['type'] ); ?>" data-obj_type="<?php echo esc_attr( $item['object'] ); ?>"></ul>
 					</div>
-				<?php
-				endforeach;
-			endif;
+					<?php
+				}
+			}
 			?>
 		</div><!-- #available-menu-items -->
 	<?php
diff --git src/wp-includes/class-wp-customize-setting.php src/wp-includes/class-wp-customize-setting.php
index 5b63822..e9ca5bf 100644
--- src/wp-includes/class-wp-customize-setting.php
+++ src/wp-includes/class-wp-customize-setting.php
@@ -968,7 +968,6 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
 			'post_title',
 			'post_type',
 			'to_ping',
-			'type_label',
 		);
 		foreach ( $irrelevant_properties as $property ) {
 			unset( $this->value[ $property ] );
@@ -1143,8 +1142,25 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
 		}
 
 		if ( ! isset( $post->type_label ) ) {
-			$post->type_label = null;
+			if ( 'post_type' === $post->type ) {
+				$object = get_post_type_object( $post->object );
+				if ( $object ) {
+					$post->type_label = $object->labels->singular_name;
+				} else {
+					$post->type_label = $post->object;
+				}
+			} elseif ( 'taxonomy' == $post->type ) {
+				$object = get_taxonomy( $post->object );
+				if ( $object ) {
+					$post->type_label = $object->labels->singular_name;
+				} else {
+					$post->type_label = $post->object;
+				}
+			} else {
+				$post->type_label = __( 'Custom Link' );
+			}
 		}
+
 		return $post;
 	}
 
diff --git tests/phpunit/tests/customize/nav-menu-item-setting.php tests/phpunit/tests/customize/nav-menu-item-setting.php
index f432517..9565d27 100644
--- tests/phpunit/tests/customize/nav-menu-item-setting.php
+++ tests/phpunit/tests/customize/nav-menu-item-setting.php
@@ -38,6 +38,17 @@ class Test_WP_Customize_Nav_Menu_Item_Setting extends WP_UnitTestCase {
 	}
 
 	/**
+	 * Filter to add a custom menu item type label. 
+	 */
+	function filter_type_label( $menu_item ) {
+		if ( 'custom_type' === $menu_item->type ) {
+			$menu_item->type_label = 'Custom Label';
+		}
+
+		return $menu_item;
+	}
+
+	/**
 	 * Test constants and statics.
 	 */
 	function test_constants() {
@@ -206,6 +217,33 @@ class Test_WP_Customize_Nav_Menu_Item_Setting extends WP_UnitTestCase {
 	}
 
 	/**
+	 * Test value method with a custom object.
+	 *
+	 * @see WP_Customize_Nav_Menu_Item_Setting::value()
+	 */
+	function test_custom_type_label() {
+		do_action( 'customize_register', $this->wp_customize );
+		add_filter( 'wp_setup_nav_menu_item', array( $this, 'filter_type_label' ) );
+
+		$menu_id = wp_create_nav_menu( 'Menu' );
+		$item_id = wp_update_nav_menu_item( $menu_id, 0, array(
+			'menu-item-type' => 'custom_type',
+			'menu-item-object' => 'custom_object',
+			'menu-item-title' => 'Cool beans',
+			'menu-item-status' => 'publish',
+		) );
+
+		$post = get_post( $item_id );
+		$menu_item = wp_setup_nav_menu_item( $post );
+
+		$setting_id = "nav_menu_item[$item_id]";
+		$setting = new WP_Customize_Nav_Menu_Item_Setting( $this->wp_customize, $setting_id );
+
+		$value = $setting->value();
+		$this->assertEquals( $menu_item->type_label, 'Custom Label' );
+	}
+
+	/**
 	 * Test value method returns zero for nav_menu_term_id when previewing a new menu.
 	 *
 	 * @see WP_Customize_Nav_Menu_Item_Setting::value()
diff --git tests/phpunit/tests/customize/nav-menus.php tests/phpunit/tests/customize/nav-menus.php
index 41991a8..f95c357 100644
--- tests/phpunit/tests/customize/nav-menus.php
+++ tests/phpunit/tests/customize/nav-menus.php
@@ -38,6 +38,36 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 	}
 
 	/**
+	 * Filter to add custom menu item types. 
+	 */
+	function filter_item_types( $items ) {
+		$items['custom_object']['custom_type'] = array(
+			'title'  => 'Custom',
+			'object' => 'custom_object',
+			'type'   => 'custom_type',
+		);
+
+		return $items;
+	}
+
+	/**
+	 * Filter to add custom menu items. 
+	 */
+	function filter_items( $items, $obj_type, $obj_name, $page ) {
+		$items[] = array(
+			'id'         => 'custom-1',
+			'title'      => 'Cool beans',
+			'type'       => $obj_name,
+			'type_label' => 'Custom Label',
+			'object'     => $obj_type,
+			'url'        => home_url( '/cool-beans/' ),
+			'classes'    => 'custom-menu-item cool-beans',
+		);
+
+		return $items;
+	}
+
+	/**
 	 * Test constructor.
 	 *
 	 * @see WP_Customize_Nav_Menus::__construct()
@@ -207,6 +237,31 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 	}
 
 	/**
+	 * Test the load_available_items_query method returns custom item.
+	 *
+	 * @see WP_Customize_Nav_Menus::load_available_items_query()
+	 */
+	function test_load_available_items_query_returns_custom_item() {
+		add_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) );
+		add_filter( 'customize_nav_menu_available_items', array( $this, 'filter_items' ), 10, 4 );
+		$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
+
+		// Expected menu item array.
+		$expected = array(
+			'id'         => 'custom-1',
+			'title'      => 'Cool beans',
+			'type'       => 'custom_type',
+			'type_label' => 'Custom Label',
+			'object'     => 'custom_object',
+			'url'        => home_url( '/cool-beans/' ),
+			'classes'    => 'custom-menu-item cool-beans',
+		);
+
+		$items = $menus->load_available_items_query( 'custom_object', 'custom_type', 0 );
+		$this->assertContains( $expected, $items );
+	}
+
+	/**
 	 * Test the search_available_items_query method.
 	 *
 	 * @see WP_Customize_Nav_Menus::search_available_items_query()
@@ -361,39 +416,34 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 	function test_available_item_types() {
 
 		$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
+
 		$expected = array(
 			'postTypes' => array(
-				'post' => array( 'label' => 'Post' ),
-				'page' => array( 'label' => 'Page' ),
+				'post' => array( 'title' => 'Post', 'object' => 'post_type', 'type' => 'post' ),
+				'page' => array( 'title' => 'Page', 'object' => 'post_type', 'type' => 'page' ),
 			),
 			'taxonomies' => array(
-				'category' => array( 'label' => 'Category' ),
-				'post_tag' => array( 'label' => 'Tag' ),
+				'category'    => array( 'title' => 'Category', 'object' => 'taxonomy', 'type' => 'category' ),
+				'post_tag'    => array( 'title' => 'Tag', 'object' => 'taxonomy', 'type' => 'post_tag' ),
 			),
 		);
+
 		if ( current_theme_supports( 'post-formats' ) ) {
-			$expected['taxonomies']['post_format'] = array( 'label' => 'Format' );
+			$expected['taxonomies']['post_format'] = array( 'title' => 'Format', 'object' => 'taxonomy', 'type' => 'post_format' );
 		}
+
 		$this->assertEquals( $expected, $menus->available_item_types() );
 
 		register_taxonomy( 'wptests_tax', array( 'post' ), array( 'labels' => array( 'name' => 'Foo' ) ) );
-		$expected = array(
-			'postTypes' => array(
-				'post' => array( 'label' => 'Post' ),
-				'page' => array( 'label' => 'Page' ),
-			),
-			'taxonomies' => array(
-				'category'    => array( 'label' => 'Category' ),
-				'post_tag'    => array( 'label' => 'Tag' ),
-				'wptests_tax' => array( 'label' => 'Foo' ),
-			),
-		);
-		if ( current_theme_supports( 'post-formats' ) ) {
-			$wptests_tax = array_pop( $expected['taxonomies'] );
-			$expected['taxonomies']['post_format'] = array( 'label' => 'Format' );
-			$expected['taxonomies']['wptests_tax'] = $wptests_tax;
-		}
+		$expected['taxonomies']['wptests_tax'] = array( 'title' => 'Foo', 'object' => 'taxonomy', 'type' => 'wptests_tax' );
+
 		$this->assertEquals( $expected, $menus->available_item_types() );
+		
+		$expected['custom_object']['custom_type'] = array( 'title' => 'Custom', 'object' => 'custom_object', 'type' => 'custom_type' );
+		
+		add_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) );
+		$this->assertEquals( $expected, $menus->available_item_types() );
+		remove_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) );
 
 	}
 
@@ -427,6 +477,7 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 	 * @see WP_Customize_Nav_Menus::available_items_template()
 	 */
 	function test_available_items_template() {
+		add_filter( 'customize_nav_menu_available_item_types', array( $this, 'filter_item_types' ) );
 		do_action( 'customize_register', $this->wp_customize );
 		$menus = new WP_Customize_Nav_Menus( $this->wp_customize );
 
@@ -442,7 +493,7 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 		if ( $post_types ) {
 			foreach ( $post_types as $type ) {
 				$this->assertContains( 'available-menu-items-' . esc_attr( $type->name ), $template );
-				$this->assertContains( '<h4 class="accordion-section-title">' . esc_html( $type->label ), $template );
+				$this->assertContains( '<h4 class="accordion-section-title">' . esc_html( $type->labels->singular_name ), $template );
 				$this->assertContains( 'data-type="' . esc_attr( $type->name ) . '" data-obj_type="post_type"', $template );
 			}
 		}
@@ -451,10 +502,14 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 		if ( $taxonomies ) {
 			foreach ( $taxonomies as $tax ) {
 				$this->assertContains( 'available-menu-items-' . esc_attr( $tax->name ), $template );
-				$this->assertContains( '<h4 class="accordion-section-title">' . esc_html( $tax->label ), $template );
+				$this->assertContains( '<h4 class="accordion-section-title">' . esc_html( $tax->labels->singular_name ), $template );
 				$this->assertContains( 'data-type="' . esc_attr( $tax->name ) . '" data-obj_type="taxonomy"', $template );
 			}
 		}
+
+		$this->assertContains( 'available-menu-items-custom_type', $template );
+		$this->assertContains( '<h4 class="accordion-section-title">Custom', $template );
+		$this->assertContains( 'data-type="custom_type" data-obj_type="custom_object"', $template );
 	}
 
 	/**
