Almost there with your PHP function. No need to set the header. function myAjaxFunc() { $posts = get_posts( array( 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'my-post-type', 'post_status' => array( 'publish', 'draft' ) ) ); $list = array(); foreach ( $posts as $post ) { $list[] = array( 'id' => $post->ID, 'name' => $post->post_title, 'link' => get_permalink( $post->ID ), ); } echo json_encode( $list ); die; } add_action( 'wp_ajax_nopriv_myAjaxFunc', 'myAjaxFunc' ); add_action( 'wp_ajax_myAjaxFunc', 'myAjaxFunc' ); And your Javascript: $.ajax({ url: "<?php bloginfo('url'); ?>/wp-admin/admin-ajax.php", type: "POST", data: "action=myAjaxFunc", success: function(results) { var posts = JSON.parse(results); console.log(results); $.each(posts, function() { $('#someSelect').append( $('<option></option>').text(this.name).val(this.id) ); }); }, error function() { console.log('Cannot retrieve data.'); } });