Google's Rich Results Test rejects schema-org LocalBusiness markup that omits required fields, stripping star ratings and address panels from search results. Beyond SEO, empty or placeholder fields in name, description, url, or address degrade the directory's data integrity: aggregators and AI crawlers that consume your structured data surface incomplete records downstream. A listing that renders "telephone": "" or "description": "TBD" in its JSON-LD signals untrustworthiness to both search engines and users who encounter the raw data via the schema-org PostalAddress or GeoCoordinates properties.
Critical because incomplete required fields cause Google to reject the structured data block entirely, making the listing ineligible for all rich result types regardless of other schema quality.
Guard against empty fields at JSON-LD construction time, not at the database layer. Use || undefined to omit absent optional fields rather than passing empty strings, which still fail validation.
// lib/listing-schema.ts
export function buildListingSchema(listing: Listing) {
return {
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": listing.name,
"description": listing.description,
"url": listing.publicUrl,
"telephone": listing.phone || undefined,
"email": listing.email || undefined,
"address": listing.address ? {
"@type": "PostalAddress",
"streetAddress": listing.address.street,
"addressLocality": listing.address.city
} : undefined,
"geo": listing.latitude && listing.longitude ? {
"@type": "GeoCoordinates",
"latitude": listing.latitude,
"longitude": listing.longitude
} : undefined
};
}
Throw a validation error during listing creation if name, description, or url are absent — reject bad data at write time.
ID: directory-listing-schema.structured-data.required-fields
Severity: critical
What to look for: Count all listing entries in the directory. For each listing, enumerate the required schema fields (name, address, phone, category, description, hours, website). for each listing page's JSON-LD, verify that name, description, url, and either telephone/email (contact) or address/geo (location) are present and non-empty.
Pass criteria: All listing pages have JSON-LD with name, description, url, and at least one contact (phone/email) or location (address/geo) field populated — at least 7 required fields must be populated per listing: name, address, phone, category, description, hours, and website. Report: "X listings checked, all Y have at least 7 required fields populated."
Fail criteria: Any required field is missing from the JSON-LD on any listing page.
Skip (N/A) when: Never — these fields are core to directory listings.
Do NOT pass when: Required fields are present but contain empty strings or placeholder values like "TBD" or "N/A".
Detail on fail: Name the missing fields. Example: "JSON-LD on 50% of pages missing description field" or "Contact properties (phone, email) are empty on all pages. Geo data not provided either."
Remediation: Ensure all required fields are populated before rendering JSON-LD:
const jsonLd = {
"@type": "LocalBusiness",
"name": listing.name,
"description": listing.description,
"url": listing.publicUrl,
"telephone": listing.phone || undefined,
"email": listing.email || undefined,
"address": listing.address ? {
"@type": "PostalAddress",
"streetAddress": listing.address.street,
"addressLocality": listing.address.city
} : undefined,
"geo": listing.latitude && listing.longitude ? {
"@type": "GeoCoordinates",
"latitude": listing.latitude,
"longitude": listing.longitude
} : undefined
}