Shortcode Customizations

Use PHP and JavaScript hooks to customize shortcode content, functionality, and styles to suite your needs.

Table of Contents

  1. Enqueueing Custom Assets
  2. JavaScript Hooks
    1. Finding Available JavaScript Hooks
  3. Untitled Project Sections

Enqueueing Custom Assets

In the 'wp_footer' action hook of WordPress, Completionist enqueues the scripts and styles for each of its shortcodes that have rendered for the current page load. As Completionist processes each detected shortcode tag, the 'ptc_completionist_shortcode_enqueue_assets' action hook in PHP is executed for third-party customizations.

Note that this action hook only runs for shortcodes that have been executed. This ensures assets are enqueued only once per page load and only when they are needed.

This sample code enqueues a custom JavaScript file and CSS stylesheet whenever the [ptc_asana_project] shortcode has been rendered at least once for the current page load:


function custom_completionist_shortcode_enqueue_assets( string $shortcode_tag ) {
  if ( 'ptc_asana_project' === $shortcode_tag ) {
      plugins_url( '/assets/js/script.js' , __FILE__ ),
      array( 'ptc-completionist-shortcode-asana-project' ),
      plugins_url( '/assets/css/styles.css' , __FILE__ ),
      array( 'ptc-completionist-shortcode-asana-project' ),

See WordPress’s documentation for usage of wp_enqueue_script() and wp_enqueue_style().

JavaScript Hooks

Completionist uses WordPress’s @wordpress/hooks npm package to implement custom action and filter hooks in JavaScript.

Using the method described above, enqueue a custom JavaScript file that registers your modifications.

This example customizes the project section “Section” label text in Completionist Pro:

  ( label, task ) => {

    // Project section names acting as statuses.
    const statuses = [
      'To Do',
      'In Progress',
      'Needs Review',
    if ( statuses.includes( task.project_section_name ) ) {
      // Label the project section as a "Status".
      label = 'Status';

    return label;

Finding Available JavaScript Hooks

The best way to find action and filter events that you can hook customizations into is by examining the following JavaScript global variables in your browser console:

// Contains the action hooks that have fired for the given client session.
window.console.log( window.Completionist.hooks.actions );
// Contains the filter hooks that have fired for the given client session.
window.console.log( window.Completionist.hooks.filters );

Note that these global variables only contain hooks that have executed at least once before you log their contents. This means you should interact with Completionist’s elements until a behavior happens or a view is displayed that you want to hook into.

If you need me to add more action or filter hooks, please let me know!

Untitled Project Sections

Despite an Asana project seeming to have untitled sections or no sections at all, the Asana API provides these sections with placeholder names. To display the same experience, Completionist ignores those placeholder names.

By default, Completionist does not display these section titles:

  • (no section)
  • untitled section
  • Untitled section
  • Untitled Section

You may choose to override which project section names are ignored by filtering the list of erased names. The Asana project’s GID and request configuration arguments are also provided for context.

This will allow all section names to be displayed, including Asana’s placeholder names:

add_filter( 'ptc_completionist_project_section_names_to_erase', 'ptc_get_project_section_names_to_erase', 10, 3 );
function ptc_get_project_section_names_to_erase( $names, $project_gid, $args ) {
  return array();

This will add another section name to be erased:

add_filter( 'ptc_completionist_project_section_names_to_erase', 'ptc_get_project_section_names_to_erase', 10, 3 );
function ptc_get_project_section_names_to_erase( $names, $project_gid, $args ) {
  $names[] = 'Section Name';
  return $names;