Customization Guide

Get Started

Customization Guide

Common customization patterns for Product Roadmap Pro. Each recipe shows a practical use case with copy-paste code you can add to your theme’s functions.php file or a custom plugin.

Time to read: 8 minutes


Before You Start

All code examples go in one of two places:

  1. Your child theme’s functions.php — Good for theme-specific customizations
  2. A custom plugin — Better for site-wide customizations that survive theme changes

Create a custom plugin by adding this file to wp-content/plugins/my-roadmap-customizations/my-roadmap-customizations.php:

Activate it under Plugins in WordPress admin.


Shortcode Reference

[roadmap] / [product_roadmap]

AttributeDefaultDescription
productmainProduct slug to display (comma-separated for multiple)
templateminimalDisplay template: board, timeline, list, cards, minimal
modeviewview for read-only, manage for drag-and-drop (requires edit_posts capability)
status(all)Comma-separated status slugs to filter
category(all)Comma-separated category slugs to filter
sort(default)Sort order: votes, recent, comments, priority
limit20Maximum items to display
orderbydateSort field: date, votes, priority, title
orderDESCSort direction: ASC or DESC
allowfrontendeditfalseEnable frontend item editing UI
class(none)Custom CSS class added to the wrapper div

[roadmap_changelog]

AttributeDefaultDescription
product(all)Filter by product slug
version(all)Show a specific version only
id(none)Show a single entry by post ID
limit10Number of entries to display
show_datetrueShow or hide the release date
collapsiblefalseMake version sections collapsible with toggle buttons
class(none)Custom CSS class added to the wrapper div

[roadmapuserprofile]

AttributeDefaultDescription
user_idCurrent userWordPress user ID to display

Template Override System

The free plugin supports theme-based template overrides. Place template files in your theme directory to customize the display without modifying plugin files.

Override Hierarchy

TemplateTheme FileFallback
Single itemsingle-roadmap_item.phpPlugin templates/single-roadmap_item.php
Product archivearchive-roadmapproduct.php or taxonomy-roadmapproduct.phpPlugin templates/archive-roadmap-product.php
All-products archivearchive-roadmap_item.phpPlugin templates/archive-roadmap_item.php
Single changelogsingle-roadmap_changelog.phpPlugin templates/single-roadmap_changelog.php
Changelog archivearchive-roadmap_changelog.phpPlugin templates/archive-roadmap_changelog.php

To override a template, copy it from the plugin’s templates/ directory into your theme’s root directory and modify as needed. Your theme’s version takes priority over the plugin’s version.


Custom Capabilities

The free plugin registers these custom capabilities on activation:

CapabilityAdminEditorAuthorContributorSubscriber
roadmap_voteYesYesYesYesYes
roadmap_commentYesYesYesYesYes
roadmap_suggestYesYesYesYesYes
roadmapedititemsYesYes
roadmapdeleteitemsYesYes
roadmapeditown_itemsYes
roadmapmanagesettingsYes
roadmapviewanalyticsYes

Capabilities are dynamically disabled when the corresponding global setting is turned off (e.g., disabling voting revokes roadmap_vote at runtime).


Voting System Details

The voting system supports three vote values:

ValueMeaning
1Upvote
0Remove vote
-1Downvote

Votes are stored in a custom {prefix}roadmapvotes database table with unique constraints preventing duplicate votes per user (by userid) or per guest (by guestip).


Status Change Notifications

When a roadmap item’s status changes, the free plugin notifies not only the admin but also all users who voted on or commented on that item. The notification system queries the votes table and comments table to build the recipient list. Results are cached for 1 hour for performance.


Customizing API Responses

View all customization code: Customization Recipes Gist

Add Custom Data to Item Responses

Use the roadmapapiformat_item filter to add extra fields to every roadmap item in API responses. This affects the shortcode display and any frontend JavaScript that reads item data.

add_filter( 'roadmap_api_format_item', function( $item_data, $item_id ) {
    // Add the item's featured image URL
    $thumbnail_id = get_post_thumbnail_id( $item_id );
    if ( $thumbnail_id ) {
        $item_data['featured_image'] = wp_get_attachment_url( $thumbnail_id );
    }

    // Add a "days since created" counter
    $created = get_the_date( 'U', $item_id );
    $item_data['days_open'] = floor( ( time() - $created ) / DAY_IN_SECONDS );

    return $item_data;
}, 25, 2 );

The priority is set to 25 so this runs after the built-in custom fields filter (priority 20).

Filter Items by Date Range

Restrict the API to only return items created within a specific date range.

add_filter( 'roadmap_api_query_args', function( $args, $request ) {
    $after = $request->get_param( 'created_after' );
    $before = $request->get_param( 'created_before' );

    if ( $after || $before ) {
        $date_query = array();
        if ( $after ) {
            $date_query['after'] = sanitize_text_field( $after );
        }
        if ( $before ) {
            $date_query['before'] = sanitize_text_field( $before );
        }
        $args['date_query'] = array( $date_query );
    }

    return $args;
}, 10, 2 );

Now you can query: /wp-json/roadmap/v1/items?createdafter=2026-01-01&createdbefore=2026-03-01


Customizing Email Notifications

Route Emails by Product

Send notification emails to different teams based on which product the item belongs to.

add_filter( 'roadmap_notification_email', function( $email, $item_id ) {
    $products = get_the_terms( $item_id, 'roadmap_product' );

    if ( ! $products || is_wp_error( $products ) ) {
        return $email; // No product assigned, use default
    }

    $routing = array(
        'mobile-app'  => 'mobile@yourcompany.com',
        'web-app'     => 'web@yourcompany.com',
        'desktop-app' => 'desktop@yourcompany.com',
    );

    $slug = $products[0]->slug;
    return isset( $routing[ $slug ] ) ? $routing[ $slug ] : $email;
}, 10, 2 );

Add a Footer to All Notification Emails

add_filter( 'roadmap_email_message', function( $message, $event_type, $item_id ) {
    $settings_url = admin_url( 'admin.php?page=roadmap-settings' );
    $footer = "\n\n---\n";
    $footer .= "Manage your notification preferences: $settings_url\n";
    $footer .= "Sent by Product Roadmap Pro";

    return $message . $footer;
}, 10, 3 );

Customize Digest Content

Add a custom section to the weekly or daily digest email.

add_filter( 'roadmap_digest_content', function( $content, $period ) {
    // Add a "stale items" section for items with no activity in 30 days
    $stale_items = get_posts( array(
        'post_type'      => 'roadmap_item',
        'posts_per_page' => 5,
        'date_query'     => array(
            array( 'before' => '30 days ago', 'column' => 'post_modified' ),
        ),
        'orderby'        => 'modified',
        'order'          => 'ASC',
    ) );

    if ( ! empty( $stale_items ) ) {
        $content .= "\n\nStale Items (no activity in 30 days)\n";
        $content .= str_repeat( '-', 40 ) . "\n";
        foreach ( $stale_items as $item ) {
            $content .= "- {$item->post_title}\n";
        }
    }

    return $content;
}, 10, 2 );

Customizing the Frontend Display

Register a Custom Template

Add your own display template alongside the built-in ones (Kanban, List, Grid, Timeline).

add_filter( 'roadmap_available_templates', function( $templates ) {
    $templates['compact'] = 'Compact View';
    return $templates;
} );

Then create the template file in your theme at roadmap/templates/compact.php.

Add Extra Data to the Shortcode

Pass additional data to the shortcode template for use in custom templates.

add_filter( 'roadmap_shortcode_data', function( $data, $atts ) {
    // Add a "product_list" for template use
    $products = get_terms( array(
        'taxonomy'   => 'roadmap_product',
        'hide_empty' => true,
    ) );
    $data['product_list'] = wp_list_pluck( $products, 'name', 'slug' );

    return $data;
}, 10, 2 );

Modify Shortcode Attributes

Set default attributes or override user-provided ones.

add_filter( 'roadmap_shortcode_atts', function( $atts ) {
    // Always default to timeline template if none specified
    if ( empty( $atts['template'] ) ) {
        $atts['template'] = 'timeline';
    }
    return $atts;
} );

Reacting to Events

Log All Status Changes

add_action( 'roadmap_status_changed', function( $item_id, $old_status, $new_status ) {
    $title = get_the_title( $item_id );
    $user = wp_get_current_user();
    $log_entry = sprintf(
        '[%s] %s changed "%s" from %s to %s',
        current_time( 'mysql' ),
        $user->display_name,
        $title,
        $old_status,
        $new_status
    );
    error_log( $log_entry );
}, 10, 3 );

Auto-Assign Product to Guest Suggestions

When a guest suggestion is submitted, automatically assign it to a default product.

add_action( 'roadmap_guest_suggestion_submitted', function( $suggestion_id ) {
    wp_set_object_terms( $suggestion_id, 'general', 'roadmap_product' );
} );

Notify Slack on High-Vote Items

Send a Slack notification when an item hits 50 votes.

add_action( 'roadmap_vote_submitted', function( $item_id, $user_id ) {
    $vote_count = get_post_meta( $item_id, '_roadmap_votes', true );

    if ( (int) $vote_count === 50 ) {
        $title = get_the_title( $item_id );
        $url = get_permalink( $item_id );

        wp_remote_post( 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL', array(
            'headers' => array( 'Content-Type' => 'application/json' ),
            'body'    => wp_json_encode( array(
                'text' => "Roadmap item \"$title\" just hit 50 votes! $url",
            ) ),
        ) );
    }
}, 10, 2 );

Working with Custom Fields Programmatically

Read Custom Field Values

Custom field values are stored as post meta with the roadmapcf_ prefix.

// Get a specific custom field value
$effort = get_post_meta( $item_id, '_roadmap_cf_effort', true );

// Get all custom fields for an item
$fields = get_post_meta( $item_id );
$custom_fields = array();
foreach ( $fields as $key => $value ) {
    if ( 0 === strpos( $key, '_roadmap_cf_' ) ) {
        $field_key = str_replace( '_roadmap_cf_', '', $key );
        $custom_fields[ $field_key ] = $value[0];
    }
}

Update Custom Field Values

update_post_meta( $item_id, '_roadmap_cf_effort', 8 );
update_post_meta( $item_id, '_roadmap_cf_target_quarter', 'Q2 2026' );

Item Meta Keys Reference

Every roadmapitem post stores its data using these postmeta keys. Use getpostmeta() (a WordPress PHP function that retrieves stored metadata for a post) to read them and updatepostmeta() to write them.

Core Meta Keys

These are set by the free plugin and available on every roadmap item.

Meta KeyTypeDescription
roadmapvotesintTotal vote count (cached — the actual votes are in the {prefix}roadmapvotes database table)
roadmapprioritystringPriority level: low, medium, high, or critical
roadmapprogressintCompletion progress percentage (0-100)
roadmaptarget_datestringTarget completion date (YYYY-MM-DD format)
roadmapassigneeintWordPress user ID of the assigned team member
roadmapcompletion_notesstringNotes visible when item is marked complete
roadmapexternal_linkstringURL to an external tracker (GitHub, Jira, etc.)
roadmapstart_datestringStart date for timeline view (YYYY-MM-DD)
roadmapend_datestringEnd date for timeline view (YYYY-MM-DD)
roadmapeffort_estimatestringEffort estimate (story points, hours, etc.)
roadmapgithub_issuestringGitHub issue URL
roadmapdependenciesarrayArray of roadmap item IDs this item depends on
roadmaporderintDisplay order within a status column (set by drag & drop)

Custom Field Meta Keys

Custom fields defined through the Pro addon are stored with the roadmapcf prefix. For example, a custom field with key effort is stored as roadmapcfeffort.

// Read a custom field
$effort = get_post_meta( $item_id, '_roadmap_cf_effort', true );

// Write a custom field
update_post_meta( $item_id, '_roadmap_cf_effort', 8 );

Guest Suggestion Meta Keys

When a guest suggestion is approved and converted to a roadmap item, these meta keys are added.

Meta KeyTypeDescription
guestsuggestion_idintOriginal guest suggestion post ID (set via REST API approval)
originalguest_idintOriginal guest suggestion post ID (set via admin row action)
guestnamestringName provided by the guest
guestemailstringEmail provided by the guest

Plugin Architecture

Understanding the plugin’s file structure helps when extending it.

FilePurpose
roadmap-pro-addon.phpMain plugin file, bootstraps all modules
class-roadmap-pro-api.phpREST API endpoint registration
class-roadmap-pro-settings.phpPro settings UI and registration
class-roadmap-pro-analytics.phpAnalytics tracking and reporting
class-roadmap-pro-custom-fields.phpCustom field definitions and meta box
class-roadmap-pro-guest-suggestions.phpGuest suggestion system
class-roadmap-pro-webhooks.phpWebhook dispatch and management
class-roadmap-pro-filters.phpAdvanced query filtering
class-roadmap-pro-templates.phpTemplate registration and management
class-roadmap-pro-products.phpMulti-product support
class-roadmap-pro-changelog.phpChangelog with product filtering
class-roadmap-pro-export.phpCSV import and export
class-roadmap-pro-merge.phpItem merging functionality

All classes use the singleton pattern. Access an instance with:

$analytics = Roadmap_Pro_Analytics::get_instance();

Next Steps


← REST API Reference | Getting Started

Last updated: March 4, 2026