davidwindham.com move. Favicon links are root-relative so every
* property (WP, /work, /rtc, /photo) can point at the same shared /favicon.* at the root.
*/
if ( ! defined( 'DW_SITE_NAME' ) ) { define( 'DW_SITE_NAME', 'David A. Windham' ); }
if ( ! defined( 'DW_TWITTER' ) ) { define( 'DW_TWITTER', '@windhamdavid' ); }
// Canonical brand domain (the consolidation target). The JSON-LD *identity* nodes point
// here. Per-page og:url / stay on the serving domain (home_url) so
// they don't point at not-yet-migrated pages; they flip automatically when siteurl moves.
if ( ! defined( 'DW_CANONICAL' ) ) { define( 'DW_CANONICAL', 'https://davidwindham.com' ); }
/** Shared favicon links (root-hosted; same files served for every property). */
function dw_seo_favicon() {
echo "\n";
echo "\n";
echo "\n";
echo "\n";
}
/** Page description: post meta_desc field -> excerpt -> site tagline. Returns a string. */
function dw_seo_description() {
if ( is_singular() ) {
$id = get_queried_object_id();
$d = trim( (string) get_post_meta( $id, 'meta_desc', true ) );
if ( $d === '' && function_exists( 'dw_good_excerpt' ) ) {
ob_start();
dw_good_excerpt( 300 );
$d = trim( (string) ob_get_clean() );
}
if ( $d !== '' ) {
return $d;
}
}
$tagline = trim( (string) get_bloginfo( 'description' ) );
return $tagline !== '' ? $tagline : DW_SITE_NAME;
}
/** OG image: the post's featured image on singulars, else the shared default. Absolute. */
function dw_seo_image() {
if ( is_singular() && has_post_thumbnail() ) {
$src = wp_get_attachment_image_src( get_post_thumbnail_id(), 'large' );
if ( $src ) {
return $src[0];
}
}
return home_url( '/og-image.jpg' ); // shared image at the web root, same-origin
}
/** Absolute URL for the current view (og:url). */
function dw_seo_url() {
if ( is_front_page() ) {
return home_url( '/' );
}
if ( is_singular() ) {
return get_permalink();
}
if ( is_category() || is_tag() || is_tax() ) {
$link = get_term_link( get_queried_object() );
if ( ! is_wp_error( $link ) ) {
return $link;
}
}
global $wp;
return home_url( '/' . ltrim( $wp->request, '/' ) );
}
/** OpenGraph + Twitter card tags for pages / archives / front page.
*
* Single POSTS are intentionally skipped — dw_opengraph() in inc/tweaks.php owns their
* OG, including the featured-video setup (og:video + twitter:player -> /container/ ->
* single-container.php). Doubling up here would emit conflicting tags and break that. */
function dw_seo_opengraph() {
if ( is_single() ) {
return;
}
$title = wp_get_document_title();
$desc = dw_seo_description();
$url = dw_seo_url();
$img = dw_seo_image();
$type = is_single() ? 'article' : 'website';
printf( "\n", esc_attr( $type ) );
printf( "\n", esc_attr( DW_SITE_NAME ) );
printf( "\n", esc_attr( $title ) );
printf( "\n", esc_attr( $desc ) );
printf( "\n", esc_url( $url ) );
printf( "\n", esc_url( $img ) );
printf( "\n" );
printf( "\n", esc_attr( DW_TWITTER ) );
printf( "\n", esc_attr( $title ) );
printf( "\n", esc_attr( $desc ) );
printf( "\n", esc_url( $img ) );
}
/** Person + WebSite JSON-LD, site-wide. */
function dw_seo_jsonld() {
$person = array(
'@context' => 'https://schema.org',
'@type' => 'Person',
'name' => DW_SITE_NAME,
'url' => DW_CANONICAL,
'image' => DW_CANONICAL . '/og-image.jpg',
'jobTitle' => 'Web Developer',
'sameAs' => array(
'https://davidwindham.com',
'https://github.com/windhamdavid',
'https://en.wikipedia.org/wiki/User:Windhamdavid',
'https://mastodon.social/@windhamdavid',
'https://www.linkedin.com/in/windhamdavid',
'https://www.facebook.com/windhamdavid',
'https://www.reddit.com/user/windhamdavid',
'https://news.ycombinator.com/user?id=windhamdavid',
),
);
$website = array(
'@context' => 'https://schema.org',
'@type' => 'WebSite',
'url' => DW_CANONICAL,
'name' => DW_SITE_NAME,
'potentialAction' => array(
'@type' => 'SearchAction',
'target' => DW_CANONICAL . '/?s={search_term_string}',
'query-input' => 'required name=search_term_string',
),
);
echo '\n";
echo '\n";
}
/** Emit the whole head block. Hooked to wp_head; front-page.php calls it directly. */
function dw_seo_head() {
dw_seo_favicon();
dw_seo_opengraph();
dw_seo_jsonld();
}
add_action( 'wp_head', 'dw_seo_head', 5 );