looking to develop a website for a recruitment agency and they want to sync their jobs board with Indeed. From chatting to the rep, they said we'll need to provide an XML feed to Indeed in the following format:


Say I was to make a custom post type and have an ACF field for each XML node, how would I go about turning all posts in that post type into an XML field?


Here's a fairly complete example of one way to do this.

Let's register a Job post type that will be used with our feed.

 * Register Job post type
 * https://developer.wordpress.org/reference/functions/register_post_type/
function wpse_register_job_post() {
    $book_args = [
        'label'              => __( 'Jobs', 'textdomain' ),
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => [ 'slug' => 'jobs' ],
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
        'supports'           => [ 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'custom-fields' ],
    register_post_type( 'jobby_job', $book_args );
add_action( 'init', 'wpse_register_job_post' );

Now for the good stuff. Let's create our custom feed and renderer. The feed can be accessed by visiting http://example.com/?feed=indeed

Register Feed

 * Create a custom feed.
 * https://developer.wordpress.org/reference/functions/add_feed/
function wpse_add_indeed_job_feed() {
    add_feed( 'indeed', 'wpse_render_indeed_job_feed' );
add_action( 'init', 'wpse_add_indeed_job_feed' );

Render Feed

 * Render our custom feed.
function wpse_render_indeed_job_feed() {
    header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );

    echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>';

<publisher><?php wp_title_rss(); ?></publisher>
<publisherurl><?php echo get_site_url(); ?></publisherurl>
<lastBuildDate><?php echo date( 'D, j M Y G:i:s' ) . ' GMT'; ?></lastBuildDate>
    // Get the job posts. Customize arguments as needed.
    $job_query = new WP_Query( [
        'post_type'      => 'jobby_job',
        'posts_per_page' => 42,
    ] );

if ( $job_query->have_posts() ) {
    while ( $job_query->have_posts() ) {

        // Note: You'll need to get the various post meta fields and add them below.
        // Use get_post_meta() or for ACF, get_field() can be used.
        // Meta is hard coded in this example.
    <title><![CDATA[<?php the_title_rss(); ?>]]></title>
    <date><![CDATA[<?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ); ?>]]></date>
    <url><![CDATA[<?php the_permalink_rss(); ?>]]></url>
    <company><![CDATA[Big ABC Corporation]]></company>
    <description><![CDATA[<?php echo get_the_content_feed( 'rss2' ); ?>]]></description>
    <salary><![CDATA[$50K per year]]></salary>
    <jobtype><![CDATA[fulltime, parttime]]></jobtype>
    <category><![CDATA[Category1, Category2, CategoryN]]></category>
    <experience><![CDATA[5+ years]]></experience>
<?php } ?>
<?php } ?>

For reference, WP's default RSS feed template is located at wp-includes/feed-rss2.php.

Remember to clear your cache when working on customizing the feed since browsers tend to cache the output.

Some other resources:

| improve this answer | |

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.