Schema markup is structured data that you add to your pages to help search engines understand your content and display rich results in search listings — star ratings, FAQ dropdowns, breadcrumbs, event dates, and recipe cards. Google uses the JSON-LD format injected into the <head> of your pages as its preferred method, and adding it to WordPress without a plugin is straightforward via a wp_head action hook. The most impactful schema types for a typical blog are Article (for posts), BreadcrumbList (improves navigation in search results), WebSite with a SearchAction (enables the sitelinks search box in Google), and FAQPage (expands FAQ content directly in search results with zero extra clicks required). Each schema type is a JSON object with a @context pointing to https://schema.org and a @type matching the schema type name. WordPress provides the data you need through its own API: get_the_title(), get_the_date(), get_the_modified_date(), get_avatar_url(), and get_the_author_meta(). Validating your markup with Google’s Rich Results Test (search.google.com/test/rich-results) before deploying is essential — invalid schema is worse than no schema because Google may penalise misleading structured data. Pair this with the canonical URL tag and Open Graph tags for a complete technical SEO setup. The snippet below injects Article schema on single posts.
Problem: You want to add JSON-LD schema markup to WordPress posts and pages to enable rich results in Google Search, without installing a full SEO plugin.
Solution: Add the following code to your functions.php file:
add_action( 'wp_head', 'helloadmin_schema_markup' );
function helloadmin_schema_markup() {
// WebSite schema (output on every page)
$website_schema = [
'@context' => 'https://schema.org',
'@type' => 'WebSite',
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
'potentialAction' => [
'@type' => 'SearchAction',
'target' => [
'@type' => 'EntryPoint',
'urlTemplate' => home_url( '/?s={search_term_string}' ),
],
'query-input' => 'required name=search_term_string',
],
];
echo '<script type="application/ld+json">' . wp_json_encode( $website_schema ) . '</script>' . "
";
// Article schema (single posts only)
if ( ! is_single() ) {
return;
}
$author_id = get_the_author_meta( 'ID' );
$article_schema = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => get_the_title(),
'url' => get_permalink(),
'datePublished' => get_the_date( 'c' ),
'dateModified' => get_the_modified_date( 'c' ),
'author' => [
'@type' => 'Person',
'name' => get_the_author(),
'url' => get_author_posts_url( $author_id ),
],
'publisher' => [
'@type' => 'Organization',
'name' => get_bloginfo( 'name' ),
'logo' => [
'@type' => 'ImageObject',
'url' => get_site_icon_url( 60 ),
],
],
'description' => wp_strip_all_tags( get_the_excerpt() ),
];
echo '<script type="application/ld+json">' . wp_json_encode( $article_schema ) . '</script>' . "
";
}
NOTE: Google requires the datePublished and dateModified dates to be in ISO 8601 format — that is why get_the_date( ‘c’ ) is used (‘c’ is PHP’s ISO 8601 date format constant). If your site icon is not set, get_site_icon_url() returns an empty string, which will cause a validation warning — either set a site icon in Appearance → Customize → Site Identity or remove the logo key from the publisher object before deploying.