# Structured data populates name, description, url, and contact or location property

- **Pattern:** `ab-001016` (`directory-listing-schema.structured-data.required-fields`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001016
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001016)

## Why it matters

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.

## Severity rationale

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.

## Remediation

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.

```ts
// 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.

## Detection

- **ID:** `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:

  ```ts
  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
  }
  ```

## External references

- schema-org LocalBusiness
- schema-org PostalAddress
- schema-org GeoCoordinates

Taxons: findability, data-integrity

HTML version: https://auditbuffet.com/patterns/ab-001016
