File: /var/www/viitorx.stgviitor.com/wp-content/themes/viitorx/inc/seo-schema.php
<?php
/**
* SEO Schema – JSON-LD (Server-Side)
*
* Outputs a consolidated @graph block in <head> via wp_head.
* All URLs are dynamic via home_url() / get_the_permalink().
*
* @package ViitorX
*/
if (! defined('ABSPATH')) exit;
// -----------------------------------------------------------------------
// Helper: Breadcrumbs
// -----------------------------------------------------------------------
function viitorx_get_breadcrumbs($site_url, $curr_url)
{
$items = [];
$pos = 1;
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => 'Home',
'item' => $site_url,
];
if (is_front_page()) {
return $items;
}
if (is_single()) {
$post_type = get_post_type();
if ($post_type === 'post') {
$cats = get_the_category();
if (! empty($cats)) {
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => $cats[0]->name,
'item' => get_category_link($cats[0]->term_id),
];
}
}
if ($post_type === 'case_study') {
$archive_url = get_post_type_archive_link('case_study');
if ($archive_url) {
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => 'Case Studies',
'item' => $archive_url,
];
}
}
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => get_the_title(),
'item' => get_permalink(),
];
return $items;
}
if (is_page()) {
$post = get_queried_object();
$parents = [];
$parent = $post->post_parent;
while ($parent) {
$p = get_post($parent);
$parents[] = [
'name' => get_the_title($p),
'item' => get_permalink($p),
];
$parent = $p->post_parent;
}
foreach (array_reverse($parents) as $p) {
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => $p['name'],
'item' => $p['item'],
];
}
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => get_the_title(),
'item' => get_permalink(),
];
return $items;
}
if (is_post_type_archive()) {
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => post_type_archive_title('', false),
'item' => $curr_url,
];
return $items;
}
if (is_category() || is_tag() || is_tax()) {
$term = get_queried_object();
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => $term->name,
'item' => $curr_url,
];
return $items;
}
$items[] = [
'@type' => 'ListItem',
'position' => $pos++,
'name' => wp_title('', false) ?: get_bloginfo('name'),
'item' => $curr_url,
];
return $items;
}
// -----------------------------------------------------------------------
// Master function — assembles and outputs the @graph
// -----------------------------------------------------------------------
function viitorx_output_schema()
{
$site_url = trailingslashit(home_url());
$org_id = $site_url . '#organization';
$site_id = $site_url . '#website';
$local_id = $site_url . '#localbusiness';
$curr_url = esc_url(home_url(add_query_arg(null, null)));
$page_id = $curr_url . '#webpage';
$is_offerings = is_page('offerings');
$is_insights = is_page('insights');
$graph = [];
// -----------------------------------------------------------------------
// 1. WebSite
// -----------------------------------------------------------------------
$graph[] = [
'@type' => 'WebSite',
'@id' => $site_id,
'url' => $site_url,
'name' => 'ViitorX',
'description' => 'ViitorX engineers immersive digital experience solutions, from permanent museum installations and VR simulations to 3D brand websites and event activations.',
'publisher' => ['@id' => $org_id],
'potentialAction' => [
'@type' => 'SearchAction',
'target' => [
'@type' => 'EntryPoint',
'urlTemplate' => $site_url . '?s={search_term_string}',
],
'query-input' => 'required name=search_term_string',
],
'inLanguage' => 'en-IN',
];
// -----------------------------------------------------------------------
// 2. Organization — Always present (referenced by others)
// -----------------------------------------------------------------------
$graph[] = [
'@type' => 'Organization',
'@id' => $org_id,
'name' => 'ViitorX',
'legalName' => 'ViitorX',
'url' => $site_url,
'logo' => [
'@type' => 'ImageObject',
'url' => $site_url . 'wp-content/uploads/2026/04/logo-x.svg',
'width' => 200,
'height' => 60,
],
'description' => 'ViitorX is an immersive experience design company building digital brand experiences, immersive experience centres, event activations, and simulation-based learning environments across India and globally.',
'foundingDate' => '2016',
'address' => [
'@type' => 'PostalAddress',
'streetAddress' => 'Avdhesh House, 301-303, opp. Gurudwara, Bodakdev',
'addressLocality' => 'Ahmedabad',
'addressRegion' => 'Gujarat',
'postalCode' => '380054',
'addressCountry' => 'IN',
],
'contactPoint' => [
'@type' => 'ContactPoint',
'telephone' => '+91-84889-64723',
'contactType' => 'customer service',
'email' => 'contact@viitorx.com',
'availableLanguage' => ['English', 'Hindi'],
],
'sameAs' => [
'https://www.linkedin.com/company/viitorx/',
'https://x.com/_ViitorX',
'https://www.instagram.com/viitorx_official/',
'https://www.facebook.com/viitorxofficial',
],
'parentOrganization' => [
'@type' => 'Organization',
'name' => 'ViitorCloud',
'url' => 'https://viitorcloud.com/',
],
'numberOfEmployees' => [
'@type' => 'QuantitativeValue',
'minValue' => 50,
'maxValue' => 200,
],
'areaServed' => ['India', 'Global'],
'knowsAbout' => [
'Immersive Experience Design',
'Virtual Reality Training',
'Augmented Reality',
'Digital Brand Experience',
'Experience Centre Design',
'Simulation-Based Learning',
],
];
// -----------------------------------------------------------------------
// 3. LocalBusiness
// -----------------------------------------------------------------------
$graph[] = [
'@type' => 'LocalBusiness',
'@id' => $local_id,
'name' => 'ViitorX',
'image' => $site_url . 'wp-content/uploads/2026/04/footer_logo.webp',
'url' => $site_url,
'telephone' => '+91-84889-64723',
'email' => 'contact@viitorx.com',
'address' => [
'@type' => 'PostalAddress',
'streetAddress' => 'Avdhesh House, 301-303, opp. Gurudwara, Bodakdev',
'addressLocality' => 'Ahmedabad',
'addressRegion' => 'Gujarat',
'postalCode' => '380054',
'addressCountry' => 'IN',
],
'geo' => [
'@type' => 'GeoCoordinates',
'latitude' => 23.0469,
'longitude' => 72.5150,
],
'openingHoursSpecification' => [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
'opens' => '09:00',
'closes' => '18:00',
],
'priceRange' => '₹₹₹',
'aggregateRating' => [
'@type' => 'AggregateRating',
'ratingValue' => '4.6',
'bestRating' => '5',
'worstRating' => '1',
'ratingCount' => '100',
],
'hasMap' => 'https://maps.google.com/?q=Avdhesh+House+Bodakdev+Ahmedabad+Gujarat',
'sameAs' => [
'https://www.linkedin.com/company/viitorx/',
'https://x.com/_ViitorX',
'https://www.instagram.com/viitorx_official/',
'https://www.facebook.com/viitorxofficial',
],
'parentOrganization' => ['@id' => $org_id],
];
// -----------------------------------------------------------------------
// 4. WebPage — always present
// CollectionPage for offerings and insights, WebPage for everything else
// -----------------------------------------------------------------------
$graph[] = [
'@type' => ($is_offerings || $is_insights) ? 'CollectionPage' : 'WebPage',
'@id' => $page_id,
'url' => $curr_url,
'name' => wp_title('', false) ?: get_bloginfo('name'),
'isPartOf' => ['@id' => $site_id],
'inLanguage' => 'en-IN',
];
// -----------------------------------------------------------------------
// 5. BreadcrumbList — linked to WebPage
// -----------------------------------------------------------------------
$breadcrumbs = viitorx_get_breadcrumbs($site_url, $curr_url);
if (count($breadcrumbs) > 1) {
$breadcrumb_id = $curr_url . '#breadcrumb';
$graph[array_key_last($graph)]['breadcrumb'] = ['@id' => $breadcrumb_id];
$graph[] = [
'@type' => 'BreadcrumbList',
'@id' => $breadcrumb_id,
'itemListElement' => $breadcrumbs,
];
}
// -----------------------------------------------------------------------
// 6. Offerings Page → 4 Services
// -----------------------------------------------------------------------
if ($is_offerings) {
$graph[] = [
'@type' => 'Service',
'@id' => $curr_url . '#digital-brand-experience',
'name' => 'Digital Brand Experience',
'description' => 'Websites and digital environments built with 3D, motion and immersive storytelling — including 3D brand websites, interactive campaign microsites, AI-personalised web experiences, and digital product showcases.',
'url' => $curr_url,
'provider' => ['@id' => $org_id],
'serviceType' => 'Digital Experience Design',
'areaServed' => 'IN',
'hasOfferCatalog' => [
'@type' => 'OfferCatalog',
'name' => 'Digital Brand Experience Services',
'itemListElement' => [
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => '3D & Motion-Rich Brand Websites']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Interactive Campaign Microsites']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'AI-Personalised Web Experiences']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Digital Product Showcases']],
],
],
];
$graph[] = [
'@type' => 'Service',
'@id' => $curr_url . '#immersive-experience-centres',
'name' => 'Immersive Experience Centres',
'description' => 'Permanent spaces that tell stories, engage visitors, and leave a lasting impact — including visitor journey planning, zone-by-zone story design, projection-mapped walls, gesture-reactive displays, and AI-driven interactive installations.',
'url' => $curr_url,
'provider' => ['@id' => $org_id],
'serviceType' => 'Experience Centre Design',
'areaServed' => 'IN',
'hasOfferCatalog' => [
'@type' => 'OfferCatalog',
'name' => 'Immersive Experience Centre Services',
'itemListElement' => [
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Visitor Journey Planning']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Projection-Mapped Walls and Floors']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Gesture and Motion-Reactive Displays']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'AI-Driven Interactive Installations']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Visitor Flow and Engagement Analytics']],
],
],
];
$graph[] = [
'@type' => 'Service',
'@id' => $curr_url . '#event-brand-experiences',
'name' => 'Event & Brand Experiences',
'description' => 'Immersive brand moments for events, expos, and product launches — including projection-mapped brand environments, 360° immersive narrative rooms, interactive exhibition stands, and AI-powered engagement analytics.',
'url' => $curr_url,
'provider' => ['@id' => $org_id],
'serviceType' => 'Event Experience Design',
'areaServed' => 'IN',
'hasOfferCatalog' => [
'@type' => 'OfferCatalog',
'name' => 'Event & Brand Experience Services',
'itemListElement' => [
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Projection-Mapped Brand Environments']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => '360° Immersive Brand Narrative Rooms']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Interactive Exhibition Stands and Pavilions']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Product Launch Experiences']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'AI-Powered Crowd and Attention Analytics']],
],
],
];
$graph[] = [
'@type' => 'Service',
'@id' => $curr_url . '#simulation-based-learning',
'name' => 'Simulation-Based Learning',
'description' => 'VR training that replaces dangerous or expensive physical practice — including VR safety and compliance training, procedural skill simulations, high-risk scenario training, AI-powered performance analysis, and LMS integration.',
'url' => $curr_url,
'provider' => ['@id' => $org_id],
'serviceType' => 'VR Training and Simulation',
'areaServed' => 'IN',
'hasOfferCatalog' => [
'@type' => 'OfferCatalog',
'name' => 'Simulation-Based Learning Services',
'itemListElement' => [
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'VR Safety and Compliance Training']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'Procedural Skill Simulations']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'High-Risk Scenario Training']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'AI-Powered Performance Analysis']],
['@type' => 'Offer', 'itemOffered' => ['@type' => 'Service', 'name' => 'LMS Integration and Compliance Reporting']],
],
],
];
}
// -----------------------------------------------------------------------
// 7. Insights Page → ItemList of Articles
// -----------------------------------------------------------------------
if ($is_insights) {
$insights = get_posts([
'post_type' => 'post',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
]);
if (! empty($insights)) {
$list_items = [];
foreach ($insights as $i => $insight) {
$item_id = get_permalink($insight);
$article = [
'@type' => 'Article',
'@id' => $item_id . '#article',
'url' => $item_id,
'headline' => get_the_title($insight),
'datePublished' => get_the_date('c', $insight),
'dateModified' => get_the_modified_date('c', $insight),
'author' => [
'@type' => 'Organization',
'name' => 'ViitorX',
'url' => $site_url,
],
'publisher' => ['@id' => $org_id],
];
$thumb_url = get_the_post_thumbnail_url($insight, 'full');
if ($thumb_url) {
$article['image'] = [
'@type' => 'ImageObject',
'url' => $thumb_url,
'width' => 1200,
'height' => 630,
];
}
$list_items[] = [
'@type' => 'ListItem',
'position' => $i + 1,
'item' => $article,
];
}
$graph[] = [
'@type' => 'ItemList',
'@id' => $curr_url . '#insights-list',
'name' => 'ViitorX Insights',
'description' => 'Thoughts, case breakdowns and industry perspectives from the ViitorX team on immersive experience design.',
'url' => $curr_url,
'itemListElement' => $list_items,
];
}
}
// -----------------------------------------------------------------------
// 8. Single Post → Article
// -----------------------------------------------------------------------
if (is_single() && get_post_type() === 'post' && ! is_front_page()) {
$post = get_queried_object();
$pub_date = get_the_date('c', $post);
$mod_date = get_the_modified_date('c', $post);
$thumb_url = get_the_post_thumbnail_url($post, 'full');
$excerpt = wp_strip_all_tags(get_the_excerpt($post));
$cats = get_the_category($post->ID);
$cat_name = ! empty($cats) ? $cats[0]->name : 'Insights';
// Keywords from Tags
$tags = get_the_tags($post->ID);
$keywords = [];
if ($tags) {
foreach ($tags as $tag) {
$keywords[] = $tag->name;
}
}
// Word Count
$word_count = str_word_count(strip_tags($post->post_content));
$article = [
'@type' => 'Article',
'@id' => get_permalink($post) . '#article',
'headline' => get_the_title($post),
'description' => $excerpt,
'url' => get_permalink($post),
'datePublished' => $pub_date,
'dateModified' => $mod_date,
'author' => [
'@type' => 'Organization',
'name' => 'ViitorX',
'url' => $site_url,
],
'publisher' => ['@id' => $org_id],
'mainEntityOfPage' => [
'@type' => 'WebPage',
'@id' => get_permalink($post),
],
'keywords' => $keywords,
'articleSection' => $cat_name,
'wordCount' => $word_count,
'inLanguage' => 'en-IN',
'isPartOf' => [
'@type' => 'Blog',
'name' => 'ViitorX Insights',
'url' => $site_url . 'insights/',
],
];
if ($thumb_url) {
$article['image'] = [
'@type' => 'ImageObject',
'url' => $thumb_url,
'width' => 1200,
'height' => 630,
];
}
$graph[] = $article;
}
// -----------------------------------------------------------------------
// 9. Single Case Study → CreativeWork
// -----------------------------------------------------------------------
if (is_single() && get_post_type() === 'case_study' && ! is_front_page()) {
$post = get_queried_object();
$pub_date = get_the_date('c', $post);
$mod_date = get_the_modified_date('c', $post);
$thumb_url = get_the_post_thumbnail_url($post, 'full');
$excerpt = wp_strip_all_tags(get_the_excerpt($post));
$creative = [
'@type' => 'CreativeWork',
'@id' => get_permalink($post) . '#casestudy',
'name' => get_the_title($post),
'description' => $excerpt,
'url' => get_permalink($post),
'datePublished' => $pub_date,
'dateModified' => $mod_date,
'creator' => ['@id' => $org_id],
'publisher' => ['@id' => $org_id],
'mainEntityOfPage' => ['@id' => $page_id],
'genre' => 'Case Study',
'inLanguage' => 'en-IN',
'isPartOf' => [
'@type' => 'CollectionPage',
'name' => 'ViitorX Case Studies',
'url' => $site_url . 'case-studies/',
],
];
if ($thumb_url) {
$creative['image'] = [
'@type' => 'ImageObject',
'url' => $thumb_url,
'width' => 1200,
'height' => 630,
];
}
$graph[] = $creative;
}
// -----------------------------------------------------------------------
// 10. Case Studies Archive → ItemList
// -----------------------------------------------------------------------
if (is_post_type_archive('case_study') && ! is_front_page()) {
$case_studies = get_posts([
'post_type' => 'case_study',
'posts_per_page' => -1,
'post_status' => 'publish',
]);
if (! empty($case_studies)) {
$list_items = [];
foreach ($case_studies as $i => $cs) {
$list_items[] = [
'@type' => 'ListItem',
'position' => $i + 1,
'url' => get_permalink($cs),
'name' => get_the_title($cs),
];
}
$graph[] = [
'@type' => 'ItemList',
'@id' => $curr_url . '#casestudies-list',
'name' => 'ViitorX Case Studies',
'url' => $curr_url,
'itemListElement' => $list_items,
];
}
}
// -----------------------------------------------------------------------
// Output
// -----------------------------------------------------------------------
$json = wp_json_encode(
['@context' => 'https://schema.org', '@graph' => $graph],
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT
);
echo '<script type="application/ld+json" class="viitorx-seo-schema">' . "\n" . $json . "\n" . '</script>' . "\n";
}
add_action('wp_head', 'viitorx_output_schema', 5);
/**
* Google Tag Manager – Production only (viitorx.com)
*
* @package ViitorX
*/
if (! defined('ABSPATH')) exit;
// Single source of truth for the GTM ID
if (! defined('VIITORX_GTM_ID')) {
define('VIITORX_GTM_ID', 'GTM-TZ2GBPS2');
}
/**
* Returns true only on the live production domain.
*/
function viitorx_is_production()
{
return isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] === 'viitorx.com';
}
/**
* GTM <head> snippet — fires before any other scripts.
*/
function viitorx_gtm_head()
{
if (! viitorx_is_production()) return;
?>
<!-- Google Tag Manager -->
<script>
(function(w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(),
event: 'gtm.js'
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', '<?php echo esc_js(VIITORX_GTM_ID); ?>');
</script>
<!-- End Google Tag Manager -->
<?php
}
add_action('wp_head', 'viitorx_gtm_head', 1);
/**
* GTM <body> snippet — fires immediately after <body> opens.
* Requires wp_body_open() to be called in header.php.
*/
function viitorx_gtm_body()
{
if (! viitorx_is_production()) return;
?>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=<?php echo esc_attr(VIITORX_GTM_ID); ?>"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<?php
}
add_action('wp_body_open', 'viitorx_gtm_body', 1);