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
The best plugins are extensible: by calling do_action() and apply_filters() at key points in your own code, you let other developers — and your own add-ons — change your plugin's behaviour without ever editing its files.
Imagine a client needs the books shortcode to show 12 books instead of your default 6. Without a hook, the only option is to edit your plugin, and the edit is lost at the next update. With a filter, they add three lines to their own code and your plugin stays untouched.
<?php
function gdc_books_get_query_args( $atts ) {
$args = array(
'post_type' => 'gdc_book',
'posts_per_page' => (int) $atts['count'],
'orderby' => 'date',
);
/**
* Filters the WP_Query arguments used by the [gdc_books] shortcode.
*
* @since 1.0.0
*
* @param array $args WP_Query arguments.
* @param array $atts The shortcode attributes.
*/
return apply_filters( 'gdc_books_query_args', $args, $atts );
}Anyone can now change the query from their own code:
<?php
// In a theme's functions.php or another plugin.
add_filter( 'gdc_books_query_args', function ( $args ) {
$args['orderby'] = 'title';
$args['order'] = 'ASC';
return $args;
} );Actions mark moments. A pair of "before" and "after" actions around anything your plugin prints gives developers a place to add their own markup:
<?php
function gdc_books_render_card( WP_Post $book ) {
ob_start();
/**
* Fires before a book card is rendered.
*
* @param WP_Post $book The book being displayed.
*/
do_action( 'gdc_books_before_card', $book );
?>
<article class="gdc-book-card">
<h3><?php echo esc_html( get_the_title( $book ) ); ?></h3>
</article>
<?php
/**
* Fires after a book card is rendered.
*
* @param WP_Post $book The book being displayed.
*/
do_action( 'gdc_books_after_card', $book );
return ob_get_clean();
}And an action after an important event lets others react to it:
<?php
// After a book's details are saved (lesson 16):
do_action( 'gdc_books_details_saved', $post_id, $isbn );
// Someone else can now sync the ISBN to an external catalogue:
add_action( 'gdc_books_details_saved', 'my_sync_isbn', 10, 2 );gdc_books_query_args, never query_args.@since with the version that introduced it.apply_filters_deprecated() and do_action_deprecated() when you must retire one, so developers get a warning first.gdc_books_query_args filter to your shortcode and use it from a theme to change the order.gdc_books_before_card and gdc_books_after_card actions and use one to add a "New" badge.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.