
🔧 How to customize WordPress headings: 4 techniques using functions.php
Headings in WordPress are more than just text at the top of a page. They work for you in four directions at once: SEO (title tag in SERP), navigation (browser tab), design (visual hierarchy on the page), and editorial control (what authors write). But the default admin settings only cover the basics; fine-tuning requires code.
The problem gets worse when multiple authors work on a site. One writes 120-character headings and breaks the layout. Another uses words your partner has banned by contract. A third forgets that the page title in SERP and on the site are two separate fields. You cannot keep track of everyone manually.
Below are four specific techniques for configuring WordPress headings through functions.php. Each solves its own task: from automatic length truncation to programmatic blocking of stop words. The code uses documented WordPress filters and has been tested on WP 6.x. At the end, you will find a FAQ section on the topic.
💡 Quick overview:
- Automatically limit heading length via the
the_titlefilter so authors cannot break the layout - Change post heading alignment through
single.phpwithout plugins or CSS edits - Block publication of posts with forbidden words via the
transition_post_statushook - Change the title tag separator and add custom titles through meta fields
How to limit WordPress heading length
A long heading can destroy even the most carefully designed layout. On the home page where excerpts are displayed, a 120-character heading spills outside the card, and the design looks broken. This hits sites with multi-column grids especially hard.
The solution is the the_title filter, which truncates the heading to a specified limit when displayed on the page. The actual record in the database remains untouched; only the displayed text is shortened.
Code for functions.php:
1 function sdstudio_limit_title_length( $title ) { 2 $max = 60; 3 if ( mb_strlen( $title ) > $max ) { 4 return mb_substr( $title, 0, $max ) . ' …'; 5 } 6 return $title; 7 } 8 add_filter( 'the_title', 'sdstudio_limit_title_length' );
Here is what happens: mb_strlen counts characters correctly for Cyrillic (unlike strlen, which counts bytes). When the 60-character limit is exceeded, the heading is truncated and an ellipsis is added at the end so readers understand this is not the full text. You can replace 60 with any other number to fit your layout.
Where to apply selectively? If you only need to truncate headings in a specific place (say, in a popular posts widget), wrap add_filter in a conditional tag:
1 if ( is_home() || is_front_page() ) { 2 add_filter( 'the_title', 'sdstudio_limit_title_length' ); 3 }
The same approach works for is_archive(), is_category(), and any other context.
How to change post heading alignment
WordPress themes vary. Some offer alignment options in the customizer; others do not. If your theme falls into the second category, the heading defaults to left alignment, and you will not find a setting for this in the admin panel.
Heading alignment is set in the single.php template, the file responsible for displaying individual posts. There are just four steps:

- Open Appearance → Theme Editor (or the
single.phpfile via FTP/hosting panel) - Find the line
<?php the_title(); ?>, which outputs the heading - Wrap it in a tag with the desired alignment
Left alignment (default):
1 <?php the_title(); ?>
Center:
1 <div style="text-align: center;"><?php the_title(); ?></div>
Right:
1 <div style="text-align: right;"><?php the_title(); ?></div>
- Save the file and open any post; the heading will appear in the specified position
This method is basic but works for any theme. A cleaner approach is to add a CSS class via the body_class filter and style through the stylesheet, but for a quick fix inline styles are sufficient.
How to block unwanted words in headings
A text warning to authors ("please do not use word X in headings") works until the first forgotten deadline. Sooner or later someone will publish a heading with a forbidden phrase, and in the best case the post will be seen internally; in the worst case, a partner or competitor will see it.
Programmatic blocking solves the problem radically: WordPress simply prevents publishing the post if the heading contains a stop word. The author sees an error message and must fix the text before publishing.

Code for functions.php:
1 function sdstudio_block_forbidden_title_words( $new_status, $old_status, $post ) { 2 if ( 'publish' !== $new_status || 'publish' === $old_status ) { 3 return; 4 } 5 6 $restricted = array( 'word1', 'word2', 'word3' ); 7 $title = $post->post_title; 8 9 foreach ( $restricted as $word ) { 10 if ( mb_stripos( $title, $word ) !== false ) { 11 wp_die( 'Ошибка: заголовок содержит запрещённое слово — «' . esc_html( $word ) . '». Измените заголовок и попробуйте снова.' ); 12 } 13 } 14 } 15 add_action( 'transition_post_status', 'sdstudio_block_forbidden_title_words', 10, 3 );
How it works: the transition_post_status hook fires on any post status change. We check that the new status is publish and the old status is not publish (otherwise every update to an already published post would also be blocked). Then mb_stripos searches for each stop word case-insensitively in the heading. If found, wp_die stops publication with a clear message.
To add your own word, replace word1, word2, word3 in the $restricted array. You can add as many words as needed; the function will iterate through all of them.
Bonus: show authors the list of forbidden words right below the title field. Add this code to the same functions.php:
1 function sdstudio_show_restricted_words_notice() { 2 $restricted = array( 'word1', 'word2', 'word3' ); 3 echo '<div style="color:#856404;background:#fff3cd;padding:6px 12px;margin:8px 0;border-radius:4px;font-size:13px;">'; 4 echo 'Запрещённые слова в заголовке: <strong>' . implode( ', ', $restricted ) . '</strong>'; 5 echo '</div>'; 6 } 7 add_action( 'edit_form_after_title', 'sdstudio_show_restricted_words_notice' );
Now the list of stop words is visible above the editor, so authors will not have to guess what is forbidden.
Title separator and custom title tags
The title separator is the symbol between the site name and the post title in <title>. In search results it appears as "Site Name | Post Title" or "Site Name - Post Title". This does not directly affect click-through rate, but it visually distinguishes your snippet from others.
Since WordPress 4.4, the separator is changed via the document_title_separator filter. The code is just three lines:
1 function sdstudio_change_title_separator( $separator ) { 2 return '|'; 3 } 4 add_filter( 'document_title_separator', 'sdstudio_change_title_separator' );
You can replace the symbol on the third line with any character: vertical bar, hyphen, greater-than sign, middle dot. Do not use special characters like ★ or →; Google does not display them, and your snippet in search results will look sloppy.
For versions below WordPress 4.4: the wp_title function is deprecated, but if your site is still on an older version, update first (this is a security matter), then adjust the separator. The old code using wp_title remains in WordPress documentation as historical reference but is not recommended.
How to set a custom title tag for an individual post
There are situations when the title tag for SERP should differ from the H1 on the page. SEO plugins (Yoast, Rank Math) provide a separate field for this. But if you do not use an SEO plugin, the task is solved with a custom field and the pre_get_document_title filter.
Code for functions.php:
1 function sdstudio_custom_title_from_meta( $title ) { 2 if ( is_singular() ) { 3 $custom = get_post_meta( get_the_ID(), 'custom_post_title', true ); 4 if ( $custom ) { 5 return esc_html( $custom ); 6 } 7 } 8 return $title; 9 } 10 add_filter( 'pre_get_document_title', 'sdstudio_custom_title_from_meta', 20 );
How to use:
- Open the post that needs a custom
<title> - In the "Custom Fields" block (if you do not see it, enable it in "Screen Options") create a field named
custom_post_title - Enter the desired title tag as the value, for example, "Caching plugin review 2026, comparison and tests"
- Save the post
If the custom field is not filled, WordPress uses the standard title tag (post title + separator + site name). The mechanism only works for singular pages (is_singular); headings on archives and in the admin area are not affected.
Important note: pre_get_document_title has priority 20, which ensures the filter runs AFTER the standard title formation and overrides it.
Watch the 6-minute video on the topic; it shows the visual process of configuring title tags through the WordPress admin and SEO plugins.
⁉️🤔 Frequently asked questions
Does the code from this article work on WordPress 6.x (the current version on wordpress.org)?
Yes, all code has been tested on the current WordPress version. The filters
the_title,document_title_separator, andpre_get_document_titlehave been part of WordPress core since versions 4.4-5.0 and are fully supported in WP 6.x. The only change from older guides: the deprecatedpublish_posthook has been replaced withtransition_post_status.
Should I edit the child theme functions.php or can I use the main one?
Always edit the child theme. If you edit the main theme's
functions.php, all changes will be lost at the next update. If you do not have a child theme, create one: it takes five minutes via the Child Theme Configurator plugin or manually (astyle.cssfile + afunctions.phpfile with theTemplate:directive).
Can I achieve the same result with plugins instead of code?
Partially. For SEO titles there are Yoast SEO and Rank Math. For length limiting, there are plugins like Title Length Limiter, but their support is unreliable. For blocking words and changing the separator, there are no standard plugins; only code works. Plus every extra plugin slows down the site, while four lines in
functions.phpadd no noticeable load.
What should I do if the site shows a white screen after editing functions.php?
Connect to the server via FTP or through your hosting file manager, open
functions.php, and delete the code you added. If you do not have FTP access, go to phpMyAdmin, find thewp_optionstable, theactive_pluginsrow, and temporarily deactivate all plugins (this will clear the cache). For the future: before any edit tofunctions.php, enableWP_DEBUGinwp-config.php; then instead of a white screen you will see the error text.
Does the title separator affect SEO?
> There is no direct effect on rankings; Google does not evaluate whether you use | or -. There is an indirect effect: Google may not display non-standard separators (★, →), and your snippet in search results will look worse visually. Also, a recognizable separator builds brand recognition: users get used to the format "Brand | Title" and notice your results in SERP faster.
What to implement and in what order
The four techniques above cover all main scenarios for working with WordPress headings. The implementation order goes from simple to complex:
First, change the title tag separator; this is three lines of code with instant results in search results. Then configure custom <title> tags through meta fields if your site has key pages that need separate SERP titles. After that, implement the length filter; it will protect the layout from overly long headings without any action from authors. Finally, add the stop word blocker once the list of forbidden phrases has been agreed upon and approved.
Before any edit to functions.php, back up the file: copy its contents to a text editor and save locally. This takes ten seconds and will save hours of recovery in case of an error.



