Hooks and filters in the Dirigible theme

  • advanced
  • php
  • hooks
  • filters
  • child-theme

Hooks are spots in the theme where your own code can run. There are two kinds:

  • Actions let you add something at that spot, such as a banner under the header or a note after every blog post.
  • Filters hand your code a value, such as a link or a block of settings, so you can change it before the theme uses it. A filter must always return the value.

This page lists the WordPress hooks and filters Dirigible Studio provides for customization. Standard WordPress and WooCommerce hooks work too but aren't covered here.

Before you start

  • Where the code goes: your child theme's functions.php, or a code snippets plugin such as Code Snippets. Never edit the parent Dirigible Studio theme. Theme updates replace its files and your changes are lost.
  • Test on a staging copy first. A typo in PHP can stop the site loading. Make sure you can reach your files through your host or SFTP so you can undo a bad change.
  • Escape what you print. Wrap text in esc_html() and links in esc_url(), as the examples below do.

Each hook below lists its arguments in the order your function receives them.

Add content to pages and posts

All of these are actions. None pass arguments except ds_post_meta.

Hook Where it runs
dirigible_after_masthead Right after the site header, on every page
dirigible_before_page_content,
dirigible_after_page_content
Before and after the content of regular pages and Landing template pages
dirigible_before_post_content,
dirigible_after_post_content
Before and after the content of blog posts and other single items that use the theme's standard layout
dirigible_before_post_footer,
dirigible_after_post_footer
Around the end of a blog post, where post details, share links, and older/newer post links appear
dirigible_before_archive_header,
dirigible_after_archive_header
Around the title area at the top of the blog and category pages
dirigible_before_archive,
dirigible_after_archive
Before and after the post list (and sidebar) on the blog page
dirigible_before_archive_posts,
dirigible_after_archive_posts
Right before and after the grid of posts
ds_post_meta At the end of a post's details (date, categories, tags). Receives $context: 'postmeta' for the main details block, 'sidebar' for the details in the post sidebar layout

Add a newsletter prompt after every blog post. Blog comments are added at the default priority (10), so priority 5 puts your prompt above them:

add_action('dirigible_after_post_content', function () {
  if (!is_singular('post')) {
    return;
  }
  echo '<p class="mt-8"><strong>Enjoyed this post?</strong> <a href="' . esc_url('/newsletter/') . '">Join our newsletter</a>.</p>';
}, 5);

Add a reading-time line to post details:

add_action('ds_post_meta', function ($context) {
  if ($context !== 'postmeta') {
    return;
  }
  $words = str_word_count(wp_strip_all_tags(get_the_content()));
  $minutes = max(1, (int) round($words / 200));
  echo '<p class="mb-0">' . esc_html($minutes . ' min read') . '</p>';
});

Header, menu, and pop-up

All actions, no arguments.

Hook Where it runs
ds_navigation_begin,
ds_navigation_end
At the start and end of the main header bar. Available on most header layouts but not Centered
ds_nav_links After the menu, search, login, and cart icons, before the header button. Also runs in the mobile menu
ds_after_logo_image Right after the logo. Anything you add here is inside the logo's home-page link
ds_utility_nav_end At the end of the utility bar above the header, when the utility bar is on
dirigible_popup_upper,
dirigible_popup_lower
At the top of the site pop-up (above the headline) and at the bottom (after the form, before the button)

Add a phone link next to the menu, using the Phone number from Footer & Contact β†’ Contact Information. ds_get_setting() reads any Dirigible Customizer value:

add_action('ds_nav_links', function () {
  $phone = ds_get_setting('ds_footer_phone');
  if (!$phone) {
    return;
  }
  $tel = preg_replace('/[^0-9+]/', '', $phone);
  echo '<a href="' . esc_url('tel:' . $tel) . '">' . esc_html($phone) . '</a>';
});

Because ds_nav_links also runs in the mobile menu, the link shows in both places.

Footer

Hook Where it runs
ds-footer The theme prints its footer here at priority 10. Use a lower number to add content above it, higher to add content below
ds-attribution The credit line at the very bottom of the page. To hide it, turn off Dirigible Attribution in Appearance β†’ Customize β†’ Settings β†’ General instead of writing code
add_action('ds-footer', function () {
  echo '<p class="py-4 text-center">' . esc_html('Proudly serving Dane County since 1998.') . '</p>';
}, 5);

Blog post links (filters)

Filter Changes Arguments
ds_post_return_link The Return to Blog link on single posts $html, $post_id
ds_prev_post_link The Older Post link $html, $prev_post, $post_id
ds_next_post_link The Newer Post link $html, $next_post, $post_id

$prev_post and $next_post are the neighboring posts. The older and newer filters also run for the smaller links in the post sidebar layout. Return an empty string to hide a link.

add_filter('ds_prev_post_link', function ($html) {
  return str_replace('Older Post', 'Previous article', $html);
});

add_filter('ds_next_post_link', function ($html) {
  return str_replace('Newer Post', 'Next article', $html);
});

Structured data (filters)

Dirigible adds structured data (JSON-LD) that tells search engines about your business and content. See Structured Data for Search Engines.

Filter Changes Arguments
ds_jsonld_global_schema The sitewide business details: name, address, contact, logo, social profiles $schema
ds_jsonld_post_type_schema The details for a single item, such as a blog post $schema, $post_type
ds_jsonld_{post_type}_schema Same, for one post type only (for example ds_jsonld_post_schema) $schema
ds_jsonld_schemas The full list of items on the page, just before output $schemas
ds_jsonld_output The final output. Return an empty value to print nothing $output

Dirigible saves the results to keep pages fast. Changes from ds_jsonld_global_schema appear after you next click Publish in the Customizer. Changes to a single item appear after you next update that post. ds_jsonld_schemas and ds_jsonld_output run on every page load.

Mark the business as a more specific type:

add_filter('ds_jsonld_global_schema', function ($schema) {
  $schema['@type'] = 'Dentist';
  $schema['priceRange'] = '$$';
  return $schema;
});

SVG uploads and inline SVG (filters)

Filter Changes Default
ds_svg_upload_capability The user capability needed to upload SVG files 'manage_options' (administrators)
ds_svg_user_can_upload The final yes or no for the current user Result of the capability check
ds_svg_allowed_tags,
ds_svg_allowed_attributes
The SVG elements and attributes kept when an upload is cleaned The built-in safe list
ds_svg_inline_class The class that marks images to swap for inline SVG 'style-svg'
ds_svg_force_inline Inline every SVG image, with or without the class false
ds_svg_skip_nested When the class is on a container, inline only images directly inside it false

The three inline filters only matter when Inline SVG is on in Appearance β†’ Customize β†’ Settings β†’ General.

Let editors upload SVGs:

add_filter('ds_svg_upload_capability', function () {
  return 'edit_pages';
});

Only widen the allowed tags and attributes if you know the SVGs come from a trusted source. The cleanup is there to block harmful code hidden in image files.

Media uploads (filters)

Dirigible stops anyone uploading an exact copy of a file that's already in the Media Library. Both filters receive $value (default false) and $file, the upload being checked. Return true to let the upload through.

Filter Use it to
dirigible_skip_duplicate_upload_check Skip the duplicate check entirely
dirigible_allow_duplicate_upload Allow the duplicate after the check

Let administrators upload duplicates:

add_filter('dirigible_allow_duplicate_upload', function ($allow) {
  return current_user_can('manage_options') ? true : $allow;
});

Dashboard and admin (filters)

Useful for agencies that want to brand the WordPress Dashboard for a client.

Filter Changes Value
ds_dashboard_welcome_description The paragraph under the Dashboard greeting A string
ds_dashboard_welcome_intro The first welcome panel ['title' => …, 'html' => …]
ds_dashboard_welcome_icon The image beside the greeting (your site icon by default) ['url' => …, 'alt' => …]
ds_dashboard_welcome_sections The list of Dashboard panels and their jump links An array of panels, each with id, label, and callback
ds_documentation_url The page shown at Dashboard β†’ Documentation A URL
add_filter('ds_dashboard_welcome_description', function () {
  return 'Need help? Email support@example.com and we will get back to you within a day.';
});

Add a Dashboard panel. The callback prints the panel and receives the panel's settings:

add_filter('ds_dashboard_welcome_sections', function ($sections) {
  $sections[] = [
    'id' => 'ds-welcome-agency',
    'label' => 'Support',
    'callback' => function ($section) {
      echo '<div id="' . esc_attr($section['id']) . '" class="ds-docs-group ds-docs-panel">';
      echo '<h2>Support</h2><p>Call us at (555) 555-0123.</p>';
      echo '</div>';
    },
  ];
  return $sections;
});

For plugin developers (filters)

These are how Dirigible's own plugins plug into the theme.

Filter Lets you Arguments
ds_admin_toasts Show a small status message (a toast) on wp-admin screens $toasts, $context
ds_sample_data_sources Add an entry to Import sample data on Dirigible β†’ Import/Export $sources

Each toast in $toasts is an array with id, token, type (working, success, error, or info), and message. Optional keys are detail, dismissible, dismiss_on_navigate, and poll_interval (milliseconds, for working toasts that should keep checking back). Toasts missing an id, token, or message are dropped.

add_filter('ds_admin_toasts', function ($toasts, $context) {
  if (get_transient('my_plugin_import_running')) {
    $toasts[] = [
      'id' => 'my-plugin/import',
      'token' => 'import-1',
      'type' => 'working',
      'message' => 'Importing products…',
      'poll_interval' => 3000,
    ];
  }
  return $toasts;
}, 10, 2);

Each sample data source is an array with id, title, an optional description, and wxr: the full path to a WordPress export file. Add requires with plugin file names (such as 'my-plugin/my-plugin.php') to show the entry only when those plugins are active.

Tools & Maintenance limits (filters)

Filter Changes Default
ds_maintenance_audit_links_max_per_post How many links Audit broken links checks per post 30
ds_maintenance_link_check_cache_ttl How long, in seconds, a link check result is remembered 300
ds_maintenance_attachment_alt_meta_key Where Sync alt tags reads each image's alt text from. Receives $key and $attachment_id WordPress's standard alt text

See Using Tools & Maintenance for what each tool does.

Related guides