$data Collected site data. */ if ( ! defined( 'ABSPATH' ) ) { exit; } // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template variables scoped to including method. $identity = $data['identity']; $content = $data['content']; $settings = $data['settings']; $technical = $data['technical']; $output = array( '$schema' => 'https://www.ai-visibility.org.uk/specifications/identity-json/identity-json.schema.json', ); if ( ! empty( $technical['language'] ) ) { $output['language'] = $technical['language']; } $output['name'] = $identity['name']; // Locale-tagged name variants (i18n specification section 2). The canonical // field above stays populated and authoritative; this is additive, and the // entry at the primary language tag repeats the canonical value because the // specification requires the two to agree. Absent unless a secondary language // actually translates the site title. if ( ! empty( $identity['name_localized'] ) && is_array( $identity['name_localized'] ) ) { $output['nameLocalized'] = $identity['name_localized']; } // Legal name if different. if ( ! empty( $identity['legal_name'] ) && $identity['legal_name'] !== $identity['name'] ) { $output['legalName'] = $identity['legal_name']; } // Alternate names (trading names, abbreviations). if ( ! empty( $content['brand_alternates'] ) ) { $output['alternateName'] = $content['brand_alternates']; } $output['url'] = $identity['url']; $output['type'] = ! empty( $identity['org_type'] ) ? $identity['org_type'] : 'Organization'; // Description is schema-required; fall back to a factual minimum. if ( ! empty( $identity['tagline'] ) ) { $output['description'] = $identity['tagline']; // Only when the description IS the tagline. The two fallbacks below are // generated here in English from other fields, so a translated tagline is // not a translation of them, and pairing them would put a value at the // primary language tag that does not match the canonical one. if ( ! empty( $identity['tagline_localized'] ) && is_array( $identity['tagline_localized'] ) ) { $output['descriptionLocalized'] = $identity['tagline_localized']; } } elseif ( ! empty( $identity['industry'] ) ) { $output['description'] = $identity['name'] . ' is a ' . $identity['industry'] . ' business.'; } else { $output['description'] = 'Official website of ' . $identity['name'] . '.'; } // Founding year (schema accepts YYYY or YYYY-MM-DD). if ( ! empty( $identity['founded'] ) ) { $output['foundingDate'] = $identity['founded']; } // Location (Schema.org PostalAddress). $location = array(); if ( ! empty( $identity['address'] ) ) { $location['streetAddress'] = $identity['address']; } if ( ! empty( $identity['city'] ) ) { $location['addressLocality'] = $identity['city']; } if ( ! empty( $identity['region'] ) ) { $location['addressRegion'] = $identity['region']; } if ( ! empty( $identity['postcode'] ) ) { $location['postalCode'] = $identity['postcode']; } // addressCountry must be ISO 3166-1 alpha-2; omitted when unmappable. if ( ! empty( $identity['country_code'] ) ) { $location['addressCountry'] = $identity['country_code']; } if ( ! empty( $location ) ) { $output['location'] = $location; } // Contact points. $contact_point = array( 'type' => 'General Enquiries' ); if ( ! empty( $identity['email'] ) ) { $contact_point['email'] = $identity['email']; } if ( ! empty( $identity['phone'] ) ) { $contact_point['telephone'] = $identity['phone']; } if ( ! empty( $identity['contact_url'] ) ) { $contact_point['url'] = $identity['contact_url']; } if ( count( $contact_point ) > 1 ) { $output['contactPoints'] = array( $contact_point ); } // Social profiles. if ( ! empty( $identity['social_links'] ) ) { $output['sameAs'] = $identity['social_links']; } // Geographic service areas. if ( ! empty( $identity['service_areas'] ) ) { $output['areaServed'] = $identity['service_areas']; } // Official identifiers. $identifiers = array(); if ( ! empty( $identity['company_number'] ) ) { $company_id = array( 'type' => 'CompanyRegistration', 'value' => $identity['company_number'], ); if ( ! empty( $identity['company_jurisdiction'] ) ) { $company_id['jurisdiction'] = $identity['company_jurisdiction']; } $identifiers[] = $company_id; } if ( ! empty( $identity['vat_number'] ) ) { $identifiers[] = array( 'type' => 'VAT', 'value' => $identity['vat_number'], ); } if ( ! empty( $identifiers ) ) { $output['identifier'] = $identifiers; } // Key people (Schema.org Person). if ( ! empty( $content['key_people'] ) ) { $people = array(); foreach ( $content['key_people'] as $person ) { if ( empty( $person['name'] ) ) { continue; } $entry = array( 'name' => $person['name'] ); if ( ! empty( $person['role'] ) ) { $entry['jobTitle'] = $person['role']; } if ( ! empty( $person['url'] ) ) { $entry['url'] = $person['url']; } $people[] = $entry; } if ( ! empty( $people ) ) { $output['employees'] = $people; } } // Extension properties (permitted by the schema; mirror the canonical example). if ( ! empty( $identity['services'] ) ) { $output['services'] = wp_list_pluck( $identity['services'], 'name' ); } if ( ! empty( $identity['not_services'] ) ) { $output['servicesNotProvided'] = $identity['not_services']; } if ( ! empty( $identity['industry'] ) ) { $output['industry'] = $identity['industry']; } if ( ! empty( $identity['employees'] ) ) { $range = AIDF_Data_Collector::parse_employee_range( $identity['employees'] ); if ( ! empty( $range ) ) { $output['numberOfEmployees'] = $range; } } if ( ! empty( $identity['customer_type'] ) ) { $output['customerType'] = $identity['customer_type']; } if ( ! empty( $identity['offering_type'] ) ) { $output['offeringType'] = $identity['offering_type']; } if ( ! empty( $identity['is_ecommerce'] ) ) { $output['isEcommerce'] = true; } if ( ! empty( $identity['not_service_areas'] ) ) { $output['areasNotServed'] = $identity['not_service_areas']; } if ( ! empty( $identity['operating_hours'] ) ) { $output['operatingHours'] = $identity['operating_hours']; } if ( ! empty( $identity['logo_url'] ) ) { $output['logo'] = $identity['logo_url']; } $legal = array(); if ( ! empty( $identity['privacy_policy_url'] ) ) { $legal['privacyPolicy'] = $identity['privacy_policy_url']; } if ( ! empty( $identity['terms_url'] ) ) { $legal['termsOfService'] = $identity['terms_url']; } if ( ! empty( $legal ) ) { $output['legal'] = $legal; } // Metadata. $output['metadata'] = array( 'lastUpdated' => wp_date( 'Y-m-d' ), ); // Cross-references (extension property; the canonical example uses relatedFiles). $active = isset( $settings['active_files'] ) ? (array) $settings['active_files'] : array(); $related_files = array(); if ( in_array( 'llms-txt', $active, true ) ) { $related_files['llms'] = home_url( '/llms.txt' ); } if ( in_array( 'ai-json', $active, true ) ) { $related_files['permissions'] = home_url( '/ai.json' ); } if ( in_array( 'brand-txt', $active, true ) ) { $related_files['brandGuidelines'] = home_url( '/brand.txt' ); } if ( ! empty( $related_files ) ) { $output['relatedFiles'] = $related_files; } // Spec attribution. $attribution = AIDF_Generator::get_json_attribution( 'identity-json' ); if ( ! empty( $attribution ) ) { $output = array_merge( $output, $attribution ); } echo wp_json_encode( $output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );