Meta Title and Meta Description Without a Plugin

Published on December 29, 2022 | Updated on August 16, 2023

I am using the GeneratePress and I am kinda obsessed with reducing the number of plugins so I am always trying to find a substitute for them.

When it comes to SEO Plugins, I think that you can keep things as simple as possible by using SLIM SEO

If you think that even a simple and lightweight plugin like SLIM SEO is too much for you, you might want to go take the coding route.

Original Code

This is a code provided by Tom from GeneratePress. it outputs a meta title and meta description that can be read by search engines.

You just have to add the code to your functions.php file.

add_action( 'wp_head', function() {
    if ( is_singular() ) {
        $meta_title = get_post_meta( get_the_ID(), 'meta_title', true );
        $meta_desc = get_post_meta( get_the_ID(), 'meta_description', true );

        if ( $meta_title ) {
            printf( '<meta name="title" content="%s">', $meta_title );

        if ( $meta_desc ) {
            printf( '<meta name="description" content="%s">', $meta_desc );
} );

You can use Advanced Custom Fields to create those two fields if you don’t want to complicate yourself.

But that still requires a plugin.

First Step: Meta Title and Meta Description without a Plugin

Add the following code to your functions.php file

add_action( 'wp_head', function() {
    if ( is_singular() ) {
        $post_id = get_the_ID();

        // Set meta title to post title if custom meta title is not set
        $meta_title = get_post_meta( $post_id, 'meta_title', true );
        if ( ! $meta_title ) {
            $meta_title = get_the_title( $post_id );

        // Set meta description to first 160 characters of post content, stripped of HTML tags, if custom meta description is not set
        $meta_desc = get_post_meta( $post_id, 'meta_description', true );
        if ( ! $meta_desc ) {
            $post_content = get_post_field( 'post_content', $post_id );
            $meta_desc = mb_substr( wp_strip_all_tags( $post_content ), 0, 160 );

        // Replace newline characters with spaces
        $meta_desc = str_replace( "\n", " ", $meta_desc );

        // Replace multiple spaces with a single space
        $meta_desc = preg_replace( '/\s+/', ' ', $meta_desc );

        // Output meta title and meta description
        if ( $meta_title ) {
            printf( '<meta name="title" content="%s">', $meta_title );
            echo "\n";  // Add a line break

        if ( $meta_desc ) {
            printf( '<meta name="description" content="%s">', $meta_desc );
			echo "\n";  // Add a line break
} );

This code:

  • Outputs the custom meta title
  • Outputs the custom meta description
  • Outputs the post title if there is a custom meta title
  • Outputs the first 160 characters if there is a custom meta description
  • Display meta titles and meta descriptions in different lines

Second Step: Creating Custom Fields

To use that code, keep in mind that you have to create two custom fields:

#1Meta Title
#2Meta Description

Here is another code snippet that can create both custom fields at the end of your posts.

function add_seo_custom_fields() {
    'seo_custom_fields', // Unique ID
    'SEO', // Box title
    'render_seo_custom_fields', // Content callback, must be of type callable
    'post', // Post type
    'normal', // Context
    'high' // Priority
add_action( 'add_meta_boxes', 'add_seo_custom_fields' );

function render_seo_custom_fields( $post ) {
  $meta_title = get_post_meta( $post->ID, 'meta_title', true );
  $meta_description = get_post_meta( $post->ID, 'meta_description', true );
  wp_nonce_field( basename( __FILE__ ), 'seo_custom_fields_nonce' );
    <label for="meta_title"><strong>Meta Title:</strong></label><br>
    <input type="text" name="meta_title" id="meta_title" maxlength="60" value="<?php echo esc_attr( $meta_title ); ?>" style="width: 100%">
    <label for="meta_description"><strong>Meta Description:</strong></label><br>
    <textarea name="meta_description" id="meta_description" maxlength="160" style="width: 100%"><?php echo esc_textarea( $meta_description ); ?></textarea>

function save_seo_custom_fields( $post_id ) {
  $is_autosave = wp_is_post_autosave( $post_id );
  $is_revision = wp_is_post_revision( $post_id );
  $is_valid_nonce = ( isset( $_POST[ 'seo_custom_fields_nonce' ] ) && wp_verify_nonce( $_POST[ 'seo_custom_fields_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false';

  if ( $is_autosave || $is_revision || !$is_valid_nonce ) {

  if ( isset( $_POST[ 'meta_title' ] ) ) {
    update_post_meta( $post_id, 'meta_title', sanitize_text_field( $_POST[ 'meta_title' ] ) );
  if ( isset( $_POST[ 'meta_description' ] ) ) {
    update_post_meta( $post_id, 'meta_description', sanitize_text_field( $_POST[ 'meta_description' ] ) );
add_action( 'save_post', 'save_seo_custom_fields' );

Third Step: Adding SEO Columns

If you want to check the meta titles and meta descriptions in the admin post lists section, add this code to your functions.php file.

//Adding SEO Custom Columns
function seo_custom_columns( $columns ) {
  $columns['meta_title'] = 'Meta Title';
  $columns['meta_description'] = 'Meta Description';
  return $columns;
add_filter( 'manage_posts_columns', 'seo_custom_columns' );

function seo_custom_columns_content( $column, $post_id ) {
  switch ( $column ) {
    case 'meta_title':
      $meta_title = get_post_meta( $post_id, 'meta_title', true );
      echo esc_html( $meta_title );
    case 'meta_description':
      $meta_description = get_post_meta( $post_id, 'meta_description', true );
      echo esc_html( $meta_description );
add_action( 'manage_posts_custom_column', 'seo_custom_columns_content', 10, 2 );

Keep this Mind

Test these codes on a copy of your site (staging site) and make sure they do what they are meant to do.

I have used them and they work for me but all sites are different so play with them in a local environment first, check the source code, and verify that the code works in a third-party tool like MetaTags.io

If you have the skills, modify the codes and make those functions better if possible.

Other Resources

You might want to check some of these resources

More Code Snippets

There are more code snippets where this came from.

Manuel Campos

Manuel Campos

I am José Manuel. I am writing about things I know and things that I am learning about WordPress. I hope you find the content of this blog useful.






© 2024 WP SURFER • Made with Love in Costa Rica