Title: _block_template_add_skip_link
Published: May 20, 2026

---

# _block_template_add_skip_link( string $template_html ): string

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#description)
 * [Parameters](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#wp--skip-link--target)

This function’s access is marked private. This means it is not intended for use 
by plugin or theme developers, only by core. It is listed here for completeness.

Inserts the block template skip-link into the template HTML.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#description)󠁿

When a `MAIN` element exists in the template, this function will ensure that the
element contains an `id` attribute, and it will insert a link to that `MAIN` element
before the first `DIV.wp-site-blocks` element, which is the wrapper for all blocks
in a block template as constructed by [get_the_block_template_html()](https://developer.wordpress.org/reference/functions/get_the_block_template_html/).

Example:

    ```php
    // Input.
    <div class="wp-site-blocks">
        <nav>...</nav>
        <main>
            <h2>...

    // Output.
    <a href="#wp--skip-link--target" id="wp-skip-link" class="...">
    <div class="wp-site-blocks">
        <nav>...</nav>
        <main id="wp--skip-link--target">
            <h2>...
    ```

When the `MAIN` element already contains a non-empty `id` value it will be used 
instead of the default skip-link id.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#parameters)󠁿

 `$template_html`stringrequired

Block template markup.

## 󠀁[Return](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#return)󠁿

 string Modified markup with skip link when applicable.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#source)󠁿

    ```php
    function _block_template_add_skip_link( string $template_html ): string {
    	// Anonymous subclass of WP_HTML_Tag_Processor to access protected bookmark spans.
    	$processor = new class( $template_html ) extends WP_HTML_Tag_Processor {
    		/**
    		 * Inserts text before the current token.
    		 *
    		 * @param string $text Text to insert.
    		 */
    		public function insert_before( string $text ) {
    			$this->set_bookmark( 'here' );
    			$this->lexical_updates[] = new WP_HTML_Text_Replacement( $this->bookmarks['here']->start, 0, $text );
    		}
    	};

    	// Find and bookmark the first DIV.wp-site-blocks.
    	if (
    		! $processor->next_tag(
    			array(
    				'tag_name'   => 'DIV',
    				'class_name' => 'wp-site-blocks',
    			)
    		)
    	) {
    		return $template_html;
    	}
    	$processor->set_bookmark( 'skip_link_insertion_point' );

    	// Ensure the MAIN element has an ID.
    	if ( ! $processor->next_tag( 'MAIN' ) ) {
    		return $template_html;
    	}

    	$skip_link_target_id = $processor->get_attribute( 'id' );
    	if ( ! is_string( $skip_link_target_id ) || '' === $skip_link_target_id ) {
    		$skip_link_target_id = 'wp--skip-link--target';
    		$processor->set_attribute( 'id', $skip_link_target_id );
    	}

    	// Seek back to the bookmarked insertion point.
    	$processor->seek( 'skip_link_insertion_point' );

    	$skip_link = sprintf(
    		'<a class="skip-link screen-reader-text" id="wp-skip-link" href="%s">%s</a>',
    		esc_url( '#' . $skip_link_target_id ),
    		/* translators: Hidden accessibility text. */
    		esc_html__( 'Skip to content' )
    	);
    	$processor->insert_before( $skip_link );

    	return $processor->get_updated_html();
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/block-template.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/7.0/src/wp-includes/block-template.php#L350)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/7.0/src/wp-includes/block-template.php#L350-L400)

## 󠀁[Related](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#related)󠁿

| Uses | Description | 
| [esc_html__()](https://developer.wordpress.org/reference/functions/esc_html__/)`wp-includes/l10n.php` |

Retrieves the translation of $text and escapes it for safe use in HTML output.

  | 
| [esc_url()](https://developer.wordpress.org/reference/functions/esc_url/)`wp-includes/formatting.php` |

Checks and cleans a URL.

  |

| Used by | Description | 
| [get_the_block_template_html()](https://developer.wordpress.org/reference/functions/get_the_block_template_html/)`wp-includes/block-template.php` |

Returns the markup for the current template.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/_block_template_add_skip_link/?output_format=md#changelog)󠁿

| Version | Description | 
| [7.0.0](https://developer.wordpress.org/reference/since/7.0.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2F_block_template_add_skip_link%2F)
before being able to contribute a note or feedback.