PolyCMS Hooks & Filters — Complete Reference
Last updated on May 16, 2026 2:04 AM
Overview
PolyCMS provides a WordPress-inspired hook and filter system that allows developers to extend functionality without modifying core module files. This is the foundation for building custom plugins and themes.
There are two types of hooks:
- Actions — Execute custom code at specific points (e.g., after a post is saved).
- Filters — Modify data before it's used (e.g., alter post content before display).
Core API Functions
Registering an Action
polycms_add_action(string $hook, callable $callback, int $priority = 10, int $args = 1);
Parameters:
$hook— Name of the action hook.$callback— Function or method to execute.$priority— Execution order (lower = earlier). Default:10.$args— Number of arguments passed to the callback. Default:1.
Example:
// Send a Slack notification when a post is published
polycms_add_action('polycms_post_published', function($post) {
$message = "New post published: {$post->title}";
send_slack_notification($message);
}, 10, 1);
Registering a Filter
polycms_add_filter(string $hook, callable $callback, int $priority = 10, int $args = 1);
Filters must return the modified value.
Example:
// Add a disclaimer to every post content
polycms_add_filter('polycms_post_content', function($content) {
return $content . '<p class="disclaimer"><em>Views expressed are the author\'s own.</em></p>';
}, 20, 1);
Triggering Hooks
// Trigger an action
polycms_do_action(string $hook, ...$args);
// Apply a filter
$value = polycms_apply_filters(string $hook, $value, ...$args);
Complete Hook Reference
Post Lifecycle Actions
| Hook | Fired When | Parameters |
|---|---|---|
polycms_post_save | Before a post is saved to DB | $data (array) |
polycms_post_saved | After a post is saved | $post (object) |
polycms_post_published | When a post status changes to published | $post (object) |
polycms_post_delete | Before a post is deleted | $post_id (int) |
polycms_post_deleted | After a post is deleted | $post_id (int) |
polycms_post_status_changed | When post status changes | $post, $old_status, $new_status |
Page Lifecycle Actions
| Hook | Fired When | Parameters |
|---|---|---|
polycms_page_saved | After a page is saved | $page (object) |
polycms_page_deleted | After a page is deleted | $page_id (int) |
Comment Actions
| Hook | Fired When | Parameters |
|---|---|---|
polycms_comment_submitted | When a new comment is submitted | $comment (object) |
polycms_comment_approved | When a comment is approved | $comment (object) |
polycms_comment_deleted | When a comment is deleted | $comment_id (int) |
Frontend Rendering Actions
| Hook | Fired When | Parameters |
|---|---|---|
polycms_head | Inside tag of frontend | — |
polycms_footer | Before of frontend | — |
polycms_frontend_init | When frontend controller initializes | — |
polycms_before_render_post | Before a single post is rendered | $post (object) |
polycms_after_render_post | After a single post is rendered | $post, $output |
polycms_after_render_homepage | After homepage renders | $output |
polycms_admin_bar_actions | Custom buttons in the admin bar | — |
Content Filters
| Filter | Applied To | Input | Expected Return |
|---|---|---|---|
polycms_post_content | Post body HTML before display | $content (string) | Modified content |
polycms_post_title | Post title before display | $title (string) | Modified title |
polycms_post_excerpt | Post excerpt before display | $excerpt (string) | Modified excerpt |
polycms_page_content | Page body HTML before display | $content (string) | Modified content |
polycms_post_meta | Post meta data | $meta (array) | Modified meta |
SEO Filters
| Filter | Applied To | Input |
|---|---|---|
polycms_meta_title | Final meta title tag | $title (string) |
polycms_meta_description | Meta description | $description (string) |
polycms_og_tags | Open Graph tag array | $tags (array) |
polycms_twitter_tags | Twitter Card tag array | $tags (array) |
Plugin & Theme Actions
| Hook | Fired When | Parameters |
|---|---|---|
polycms_plugin_activated | When a plugin is activated | $plugin_slug |
polycms_plugin_deactivated | When a plugin is deactivated | $plugin_slug |
polycms_theme_switched | When active theme changes | $new_theme, $old_theme |
Practical Examples
Example 1: Auto-Generate Excerpt
polycms_add_filter('polycms_post_excerpt', function($excerpt) {
if (empty($excerpt)) {
$CI = &get_instance();
$content = $CI->load->get_var('post')->content ?? '';
return mb_substr(strip_tags($content), 0, 160) . '...';
}
return $excerpt;
});
Example 2: Inject Google Tag Manager
polycms_add_action('polycms_head', function() {
$gtm_id = get_option('polycms_gtm_id');
if ($gtm_id) {
echo "<script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','{$gtm_id}');</script>";
}
});
Example 3: Restrict Post Content to Logged-in Users
polycms_add_filter('polycms_post_content', function($content) {
$CI = &get_instance();
$post = $CI->load->get_var('post');
if ($post->visibility === 'private' && !is_staff_logged_in()) {
return '<div class="restricted"><p>This content is available to registered members only.</p></div>';
}
return $content;
});
Best Practices
- Always use priority numbers to control execution order. Default is
10. - Filters must return a value — forgetting to return will break the data chain.
- Use unique function names or closures to avoid conflicts between plugins.
- Don't modify global state inside filters — only transform and return the input data.
- Test with a single plugin first before combining multiple hooks to isolate issues.
Related Documentation
- Building a Custom Plugin — Use these hooks inside a plugin scaffold.
- Building a Custom Theme — Use frontend hooks in theme templates.
- Template Tags & Helpers — Helper functions available in templates.
- Architecture Overview — Understand the request lifecycle and where hooks are triggered.