{"id":312,"date":"2026-06-26T13:01:29","date_gmt":"2026-06-26T13:01:29","guid":{"rendered":"https:\/\/tools.dwiyanti.com\/blog\/?p=312"},"modified":"2026-06-26T13:01:29","modified_gmt":"2026-06-26T13:01:29","slug":"schema-webpage-versi-claude","status":"publish","type":"post","link":"https:\/\/tools.dwiyanti.com\/blog\/schema-webpage-versi-claude","title":{"rendered":"Schema WebPage Versi Claude"},"content":{"rendered":"<pre style=\"white-space:pre-wrap;\">\n\/\/ =============================================================================\n\/\/ SCHEMA WEBPAGE \u2014 dwiyanti.com\n\/\/ Versi: 2.0 \u2014 Full SEO Modern + AI Overview Optimization\n\/\/ Update: @id, url, isPartOf, primaryImageOfPage, inLanguage, breadcrumb,\n\/\/         speakable, ImageObject @id, WebPage @type spesifik\n\/\/ =============================================================================\n\nfunction add_webpage_schema() {\n\n    \/\/ \u2500\u2500 Guard: Keluar jika Home atau bukan page \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    if ( is_front_page() || is_home() ) return;\n    if ( ! is_page() ) return;\n\n    global $post;\n    if ( $post->post_title === 'Home' || $post->post_name === 'home' ) return;\n\n    \/\/ \u2500\u2500 DATA DASAR \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    $title       = get_the_title( $post );\n    $url         = get_permalink( $post );\n    $published   = get_the_date( 'c', $post );\n    $modified    = get_the_modified_date( 'c', $post );\n    $description = get_optimized_meta_description(); \/\/ fungsi existing\n    $site_icon   = get_site_icon_url();\n    $site_url    = home_url();\n\n    \/\/ \u2500\u2500 BAHASA KONTEN \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    \/\/ Sesuaikan per halaman jika kamu punya mixed-language content.\n    \/\/ Untuk dwiyanti.com yang mayoritas Bahasa Indonesia:\n    $in_language = 'id-ID';\n\n    \/\/ \u2500\u2500 AMBIL SEMUA GAMBAR (UNIVERSAL) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    $images        = [];\n    $primary_image = null;\n\n    \/\/ 1. Featured Image \u2014 jadikan primary image\n    if ( has_post_thumbnail( $post->ID ) ) {\n        $image_id   = get_post_thumbnail_id( $post->ID );\n        $image_url  = wp_get_attachment_image_url( $image_id, 'full' );\n        $image_meta = wp_get_attachment_metadata( $image_id );\n        $image_alt  = get_post_meta( $image_id, '_wp_attachment_image_alt', true );\n        $image_cap  = wp_get_attachment_caption( $image_id );\n\n        $primary_image = [\n            '@type'      => 'ImageObject',\n            '@id'        => $image_url . '#primaryimage',\n            'url'        => $image_url,\n            'contentUrl' => $image_url,\n            'width'      => isset( $image_meta['width'] )  ? $image_meta['width']  : 1200,\n            'height'     => isset( $image_meta['height'] ) ? $image_meta['height'] : 630,\n        ];\n\n        if ( ! empty( $image_alt ) ) {\n            $primary_image['name'] = $image_alt;\n        }\n        if ( ! empty( $image_cap ) ) {\n            $primary_image['caption'] = $image_cap;\n        }\n\n        $images[] = $primary_image;\n    }\n\n    \/\/ 2. Gambar dari konten post (semua, tanpa batas)\n    $content = get_post_field( 'post_content', $post->ID );\n    preg_match_all( '\/<img[^>]+src=[\"\\']([^\"\\']+)[\"\\']\/i', $content, $matches );\n\n    if ( ! empty( $matches[1] ) ) {\n        foreach ( $matches[1] as $img_url ) {\n            \/\/ Skip duplikat\n            $is_duplicate = false;\n            foreach ( $images as $img ) {\n                if ( $img['url'] === $img_url ) {\n                    $is_duplicate = true;\n                    break;\n                }\n            }\n            if ( ! $is_duplicate ) {\n                $images[] = [\n                    '@type'      => 'ImageObject',\n                    '@id'        => $img_url . '#image',\n                    'url'        => $img_url,\n                    'contentUrl' => $img_url,\n                    'width'      => 1200,\n                    'height'     => 630,\n                ];\n            }\n        }\n    }\n\n    \/\/ 3. Fallback jika zero gambar\n    if ( empty( $images ) ) {\n        $fallback_url  = 'https:\/\/dwiyanti.com\/wp-content\/themes\/lifestyle\/assets\/images\/DwiYanti.jpeg';\n        $primary_image = [\n            '@type'      => 'ImageObject',\n            '@id'        => $fallback_url . '#primaryimage',\n            'url'        => $fallback_url,\n            'contentUrl' => $fallback_url,\n            'width'      => 1200,\n            'height'     => 630,\n            'name'       => 'Dwi Yanti',\n        ];\n        $images[] = $primary_image;\n    }\n\n    \/\/ \u2500\u2500 DETEKSI KATEGORI & WEBPAGE TYPE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    $webpage_type    = 'WebPage';   \/\/ default\n    $primary_category = '';\n    $about_entity    = null;\n    $categories      = get_the_category();\n\n    if ( ! empty( $categories ) ) {\n        $primary_category = $categories[0]->name;\n        $cat_lower        = strtolower( $primary_category );\n\n        if ( in_array( $cat_lower, [ 'beauty', 'skincare', 'makeup' ] ) ) {\n            $webpage_type  = 'WebPage'; \/\/ Beauty tidak ada sub-type resmi di WebPage\n            $about_entity  = [ '@type' => 'Thing', 'name' => $primary_category ];\n        } elseif ( in_array( $cat_lower, [ 'health', 'wellness', 'fitness' ] ) ) {\n            $webpage_type  = 'MedicalWebPage';\n            $about_entity  = [ '@type' => 'MedicalCondition', 'name' => $primary_category ];\n        } elseif ( in_array( $cat_lower, [ 'lifestyle', 'travel', 'fashion' ] ) ) {\n            $webpage_type  = 'WebPage';\n            $about_entity  = [ '@type' => 'Thing', 'name' => $primary_category ];\n        }\n    }\n\n    \/\/ \u2500\u2500 BREADCRUMB \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    $breadcrumb_items = [\n        [\n            '@type'    => 'ListItem',\n            'position' => 1,\n            'name'     => 'Home',\n            'item'     => $site_url . '\/',\n        ],\n    ];\n\n    \/\/ Tambah kategori jika ada\n    if ( ! empty( $primary_category ) && ! empty( $categories ) ) {\n        $cat_link = get_category_link( $categories[0]->term_id );\n        $breadcrumb_items[] = [\n            '@type'    => 'ListItem',\n            'position' => 2,\n            'name'     => $primary_category,\n            'item'     => $cat_link,\n        ];\n        $breadcrumb_items[] = [\n            '@type'    => 'ListItem',\n            'position' => 3,\n            'name'     => $title,\n            'item'     => $url,\n        ];\n    } else {\n        $breadcrumb_items[] = [\n            '@type'    => 'ListItem',\n            'position' => 2,\n            'name'     => $title,\n            'item'     => $url,\n        ];\n    }\n\n    $breadcrumb_schema = [\n        '@type'           => 'BreadcrumbList',\n        '@id'             => $url . '#breadcrumb',\n        'itemListElement' => $breadcrumb_items,\n    ];\n\n    \/\/ \u2500\u2500 BANGUN WEBPAGE SCHEMA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    $webpage = [\n        '@type'          => $webpage_type,\n        '@id'            => $url . '#webpage',\n        'url'            => $url,\n        'name'           => $title,\n        'headline'       => $title,\n        'description'    => $description,\n        'inLanguage'     => $in_language,\n        'isPartOf'       => [\n            '@type' => 'WebSite',\n            '@id'   => $site_url . '\/#website',\n        ],\n        'breadcrumb'     => [\n            '@id' => $url . '#breadcrumb',\n        ],\n        'datePublished'  => $published,\n        'dateModified'   => $modified,\n        'author'         => [\n            '@type' => 'Person',\n            'name'  => 'Dwi Yanti',\n            '@id'   => 'https:\/\/me.dwiyanti.com\/#dwi-yanti',\n        ],\n        'publisher'      => [\n            '@type'         => 'Organization',\n            '@id'           => $site_url . '\/#organization',\n            'name'          => 'Dwi Yanti SEO',\n            'alternateName' => 'Dwi Yanti SEO Specialist & Technical SEO Strategist',\n            'logo'          => [\n                '@type' => 'ImageObject',\n                'url'   => $site_icon,\n            ],\n        ],\n        'image'          => $images,\n        \/\/ Speakable \u2014 bantu AI Assistant & Google SGE memilih konten utama\n        'speakable'      => [\n            '@type'       => 'SpeakableSpecification',\n            'cssSelector' => [ 'h1', '.entry-content p:first-of-type', '.post-excerpt' ],\n        ],\n    ];\n\n    \/\/ Primary image \u2014 hanya kalau ada\n    if ( ! is_null( $primary_image ) ) {\n        $webpage['primaryImageOfPage'] = [\n            '@id' => $primary_image['@id'],\n        ];\n    }\n\n    \/\/ About entity \u2014 sesuai kategori\n    if ( ! is_null( $about_entity ) ) {\n        $webpage['about'] = $about_entity;\n    }\n\n    \/\/ \u2500\u2500 BANGUN @GRAPH \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    $schema = [\n        '@context' => 'https:\/\/schema.org',\n        '@graph'   => [\n            $breadcrumb_schema,\n            $webpage,\n        ],\n    ];\n\n    \/\/ \u2500\u2500 OUTPUT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    echo '<script type=\"application\/ld+json\">' . \"\\n\";\n    echo wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );\n    echo \"\\n\" . '<\/script>' . \"\\n\";\n}\nadd_action( 'wp_head', 'add_webpage_schema' );\n\/\/ END WebPage Schema\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\/\/ ============================================================================= \/\/ SCHEMA WEBPAGE \u2014 dwiyanti.com \/\/ Versi: 2.0 \u2014 Full SEO Modern + AI Overview Optimization \/\/ Update: @id, url, isPartOf, primaryImageOfPage, inLanguage, breadcrumb, \/\/ speakable, ImageObject @id, WebPage @type spesifik \/\/ ============================================================================= function add_webpage_schema() { \/\/ \u2500\u2500 Guard: Keluar jika Home atau bukan page \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 if ( is_front_page() || is_home() ) return; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-312","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/posts\/312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/comments?post=312"}],"version-history":[{"count":1,"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/posts\/312\/revisions"}],"predecessor-version":[{"id":313,"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/posts\/312\/revisions\/313"}],"wp:attachment":[{"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/media?parent=312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/categories?post=312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tools.dwiyanti.com\/blog\/wp-json\/wp\/v2\/tags?post=312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}