Build WordPress plugins from scratch: actions and filters, shortcodes, settings pages, custom post types, meta boxes, AJAX, REST endpoints, custom tables, cron and blocks.
Lessons
A filter hook passes a value through every function registered with add_filter() before WordPress uses it, so your plugin can change titles, content, excerpt lengths or query results without touching the code that produced them.
<?php
function gdc_books_excerpt_length( $length ) {
return 30; // Words. Default is 55.
}
add_filter( 'excerpt_length', 'gdc_books_excerpt_length' );WordPress calls apply_filters( 'excerpt_length', 55 ). The value goes into your function, and whatever you return is what WordPress uses. Forget the return and the value becomes null — every excerpt on the site disappears.
Many filters pass the value plus extra arguments that describe it. Accept them by setting the fourth parameter:
<?php
/**
* Prefixes the title of Book posts with a book emoji, on the front end only.
*
* @param string $title The post title.
* @param int $post_id The post ID.
* @return string
*/
function gdc_books_title_prefix( $title, $post_id = 0 ) {
if ( is_admin() || ! $post_id ) {
return $title;
}
if ( 'gdc_book' === get_post_type( $post_id ) ) {
return '📘 ' . $title;
}
return $title;
}
add_filter( 'the_title', 'gdc_books_title_prefix', 10, 2 );Notice the early returns that hand the value back unchanged when it is not one you want to modify. A filter should be a precise scalpel: change only what you mean to, and pass everything else straight through.
| Filter | Value passed | Use it to |
|---|---|---|
the_content | Post HTML | Add notices, ads, related books |
the_title | Title string | Prefix or modify titles |
excerpt_length / excerpt_more | Number / string | Control excerpts |
body_class | Array of classes | Add a class to <body> |
upload_mimes | Allowed file types | Allow or block uploads |
plugin_action_links_{basename} | Links under your plugin | Add a "Settings" link |
wp_mail_from_name | Sender name | Brand outgoing email |
<?php
function gdc_books_action_links( $links ) {
$settings = sprintf(
'<a href="%s">%s</a>',
esc_url( admin_url( 'options-general.php?page=gdc-books' ) ),
esc_html__( 'Settings', 'gdc-books' )
);
array_unshift( $links, $settings ); // Put it first.
return $links;
}
add_filter( 'plugin_action_links_' . GDC_BOOKS_BASENAME, 'gdc_books_action_links' );the_content filter without checks also runs in feeds, excerpts and the REST API. Guard it with conditions like is_singular() and in_the_loop().excerpt_more.gdc-books-active class to <body> with the body_class filter.In accordance with Section 6 & Section 7 of the DPDP Act 2023, third-party analytics and marketing trackers are strictly gated behind your affirmative consent. You may withdraw consent at any time under Section 6(4).
Essential for session authentication (ci_session), Cross-Site Request Forgery security (csrf_cookie_name), and Cloudflare DDoS/bot prevention. Cannot be disabled.
Gated under DPDP Section 7. Allows Google Analytics 4 (Google Consent Mode v2) to measure aggregate, anonymized tool usage.
Enables browser local storage to preserve your theme selection (dark/light mode) and code editor layout between visits.
Used to display developer sponsorships and native tool partner notices.