Shared Types

Shared building blocks used across multiple schema types. Import them to compose rich nested schemas.

Table of contents

  1. PostalAddressSchema
  2. GeoCoordinatesSchema
  3. ImageObjectSchema / ImageOrUrl / createImageObject
    1. ImageObject fields
    2. ImageOrUrl
  4. ContactPointSchema
  5. MonetaryAmountSchema / PriceSpecificationSchema
  6. RatingSchema / AggregateRatingSchema / ReviewSchema
    1. RatingSchema
    2. AggregateRatingSchema
    3. ReviewSchema
    4. EmployerAggregateRatingSchema
  7. OfferSchema / createOffer / ItemAvailability / ItemCondition
    1. Offer fields
    2. ItemAvailability values
    3. ItemCondition values
    4. UnitPriceSpecificationSchema
  8. AggregateOfferSchema
    1. Fields
  9. OfferShippingDetailsSchema / DefinedRegionSchema / ShippingDeliveryTimeSchema
    1. OfferShippingDetailsSchema fields
    2. DefinedRegionSchema fields
    3. ShippingDeliveryTimeSchema fields
    4. Example — Free US shipping
  10. MerchantReturnPolicySchema
    1. Fields
  11. OpeningHoursSpecificationSchema
  12. HowToStepSchema / HowToSectionSchema
  13. PersonOrOrgRef
  14. ClipSchema / BroadcastEventSchema / SeekToActionSchema / VideoObjectSchema
  15. InteractionCounterSchema
  16. MemberProgramSchema / MemberProgramTierSchema
    1. MemberProgramTierSchema fields
    2. MemberProgramSchema fields
  17. ShippingServiceSchema / ShippingConditionsSchema / ServicePeriodSchema
    1. ShippingServiceSchema fields
    2. ShippingConditionsSchema fields
    3. ServicePeriodSchema fields

PostalAddressSchema

import { PostalAddressSchema, type PostalAddress } from 'schemaorg-kit';

Physical mailing address. Use with Organization.address, LocalBusiness.address, JobPosting.jobLocation, etc.

const address = PostalAddressSchema.parse({
  streetAddress: '123 Main Street',
  addressLocality: 'San Francisco',   // city
  addressRegion: 'CA',                 // state/province
  postalCode: '94105',
  addressCountry: 'US',               // ISO 3166-1 alpha-2
  postOfficeBoxNumber: 'PO Box 123',  // optional
});
// { "@type": "PostalAddress", ... }

You can also pass a plain object literal directly — any field accepting PostalAddress also accepts the raw object shape.


GeoCoordinatesSchema

import { GeoCoordinatesSchema, type GeoCoordinates } from 'schemaorg-kit';

GPS coordinates. Used with LocalBusiness.geo, Place.geo, VacationRental.geo.

const geo = GeoCoordinatesSchema.parse({
  latitude: 37.78825,
  longitude: -122.4324,
});
// { "@type": "GeoCoordinates", "latitude": 37.78825, "longitude": -122.4324 }

ImageObjectSchema / ImageOrUrl / createImageObject

import {
  ImageObjectSchema,
  ImageOrUrl,
  createImageObject,
  type ImageObject,
} from 'schemaorg-kit';

A detailed image object with Google image metadata fields.

ImageObject fields

Field Type Notes
url string Required — image URL
contentUrl string? Direct file URL (if different from page URL)
width number \| QuantitativeValue? Pixel width
height number \| QuantitativeValue? Pixel height
caption string? Image caption
description string? Image description
name string? Image name/title
creator Person \| Organization? Who created the image
creditText string? Credit line to display
copyrightNotice string? Copyright notice
license string? License URL
acquireLicensePage string? Where to get a license
representativeOfPage boolean? Primary image of its page
encodingFormat string? MIME type, e.g. "image/jpeg"
uploadDate string? ISO 8601 upload date
thumbnailUrl string? Thumbnail URL
const image = createImageObject({
  url: 'https://example.com/photo.jpg',
  width: 1200,
  height: 675,
  caption: 'Team at the annual conference',
  creator: { '@type': 'Person', name: 'Bob Chen' },
  creditText: 'Photo by Bob Chen / Acme Corp',
  license: 'https://creativecommons.org/licenses/by/4.0/',
});

ImageOrUrl

ImageOrUrl accepts either a URL string or a full ImageObject. It’s used on fields like Thing.image, Organization.logo, Article.image, etc.:

// Both are valid:
{ image: 'https://example.com/photo.jpg' }
{ image: { '@type': 'ImageObject', url: 'https://example.com/photo.jpg', width: 1200 } }

// Arrays are also accepted on most types:
{ image: ['https://example.com/1.jpg', 'https://example.com/2.jpg'] }

ContactPointSchema

import { ContactPointSchema, type ContactPoint } from 'schemaorg-kit';

A specific contact channel. Used in Organization.contactPoint.

const contact = ContactPointSchema.parse({
  contactType: 'customer support',   // required
  telephone: '+1-800-555-0100',
  email: 'support@example.com',      // must be valid email
  availableLanguage: ['English', 'Spanish'],
  hoursAvailable: 'Mo-Fr 09:00-18:00',
  contactOption: 'TollFree',
  areaServed: 'US',
});

MonetaryAmountSchema / PriceSpecificationSchema

import { MonetaryAmountSchema, PriceSpecificationSchema } from 'schemaorg-kit';

Used for JobPosting.baseSalary and VacationRental pricing.

// Salary range
const salary = MonetaryAmountSchema.parse({
  currency: 'USD',
  value: {
    '@type': 'QuantitativeValue',
    minValue: 80000,
    maxValue: 120000,
    unitText: 'YEAR',   // or 'HOUR', 'MONTH', 'WEEK'
  },
});

// Single price
const price = PriceSpecificationSchema.parse({
  price: 9.99,
  priceCurrency: 'USD',
  valueAddedTaxIncluded: true,
  validFrom: '2025-01-01',
  validThrough: '2025-12-31',
});

RatingSchema / AggregateRatingSchema / ReviewSchema

import {
  RatingSchema,
  AggregateRatingSchema,
  ReviewSchema,
  EmployerAggregateRatingSchema,
  type Rating,
  type AggregateRating,
  type Review,
} from 'schemaorg-kit';

RatingSchema

A single rating value.

const rating = RatingSchema.parse({
  ratingValue: 4.5,
  bestRating: 5,      // default if omitted
  worstRating: 1,     // default if omitted
  ratingExplanation: 'Great product, fast shipping.',
  reviewAspect: 'quality',
});

AggregateRatingSchema

Average across many ratings. Either ratingCount or reviewCount is required.

const aggregateRating = AggregateRatingSchema.parse({
  ratingValue: 4.7,
  ratingCount: 12400,  // total number of ratings
  reviewCount: 890,    // total number of written reviews
  bestRating: 5,
  worstRating: 1,
});

ReviewSchema

An individual user review.

const review = ReviewSchema.parse({
  author: { '@type': 'Person', name: 'Jane Smith' },
  reviewRating: { '@type': 'Rating', ratingValue: 5, bestRating: 5 },
  reviewBody: 'Exceptional product. Well worth the price.',
  datePublished: '2025-02-14',
  publisher: { '@type': 'Organization', name: 'Trustpilot' },
  itemReviewed: { '@type': 'Product', name: 'Trail Runner Pro' },
});

EmployerAggregateRatingSchema

For employer ratings (Glassdoor-style).

const rating = EmployerAggregateRatingSchema.parse({
  ratingValue: 4.1,
  ratingCount: 2340,
  bestRating: 5,
  worstRating: 1,
  itemReviewed: { '@type': 'Organization', name: 'Acme Corp' },
});

OfferSchema / createOffer / ItemAvailability / ItemCondition

import {
  OfferSchema, createOffer, ItemAvailability, ItemCondition,
  UnitPriceSpecificationSchema,
  type Offer,
} from 'schemaorg-kit';

Pricing information for products, apps, courses, events, etc.

Offer fields

Field Type Notes
price number \| string Price (use 0 for free)
priceCurrency string ISO 4217 code (3 chars), e.g. "USD"
availability ItemAvailability? Auto-transforms to schema.org URL
itemCondition ItemCondition? Auto-transforms to schema.org URL
url string? Purchase URL
priceValidUntil string? ISO 8601 expiry date
validFrom string? Offer start date
validThrough string? Offer end date
seller { @type, name }? Who is selling
category string? Offer category
inventoryLevel QuantitativeValue? Stock level
priceSpecification UnitPriceSpecification \| []? Loyalty/unit pricing (see below)
shippingDetails OfferShippingDetails \| []? Shipping info (see below)
hasMerchantReturnPolicy MerchantReturnPolicy? Return policy

ItemAvailability values

Input Transformed output
"InStock" https://schema.org/InStock
"OutOfStock" https://schema.org/OutOfStock
"PreOrder" https://schema.org/PreOrder
"SoldOut" https://schema.org/SoldOut
"LimitedAvailability" https://schema.org/LimitedAvailability
"OnlineOnly" https://schema.org/OnlineOnly
"InStoreOnly" https://schema.org/InStoreOnly
"BackOrder" https://schema.org/BackOrder
"Discontinued" https://schema.org/Discontinued

ItemCondition values

Input Transformed output
"NewCondition" https://schema.org/NewCondition
"UsedCondition" https://schema.org/UsedCondition
"RefurbishedCondition" https://schema.org/RefurbishedCondition
"DamagedCondition" https://schema.org/DamagedCondition
// Using createOffer factory (returns SchemaNode)
const offer = createOffer({
  price: 29.99,
  priceCurrency: 'USD',
  availability: 'InStock',       // → "https://schema.org/InStock"
  itemCondition: 'NewCondition', // → "https://schema.org/NewCondition"
  priceValidUntil: '2025-12-31',
  url: 'https://example.com/buy',
});

// Using OfferSchema directly (returns plain object)
const offerObj = OfferSchema.parse({
  price: 0,
  priceCurrency: 'USD',
  availability: 'InStock',
});

UnitPriceSpecificationSchema

For loyalty pricing, member-tier pricing, or unit-based pricing on Google Merchant Listings.

Field Type Notes
price number \| string Required
priceCurrency string Required — ISO 4217 (3 chars)
priceType string? "SRP", "ListPrice", "SalePrice", etc.
validForMemberTier string \| object? Member tier this price applies to
referenceQuantity QuantitativeValue? Unit reference (e.g. per 100g)
membershipPointsEarned QuantitativeValue? Loyalty points earned
validFrom string? ISO 8601
validThrough string? ISO 8601
import { UnitPriceSpecificationSchema } from 'schemaorg-kit';

const loyaltyPrice = UnitPriceSpecificationSchema.parse({
  price: 24.99,
  priceCurrency: 'USD',
  priceType: 'SalePrice',
  validForMemberTier: { '@type': 'MemberProgramTier', name: 'Gold' },
  membershipPointsEarned: { '@type': 'QuantitativeValue', value: 50 },
});

AggregateOfferSchema

import { AggregateOfferSchema, type AggregateOffer } from 'schemaorg-kit';

For products sold by multiple sellers at different prices. Use in place of (or alongside) OfferSchema on Product.offers.

Fields

Field Type Notes
lowPrice number? Lowest available price
highPrice number? Highest available price
priceCurrency string? ISO 4217 currency code (3 chars)
offerCount number? Number of sellers
offers Offer \| Offer[]? Individual seller offers
availability ItemAvailability? Overall availability
url string? Canonical product URL
import { createProduct, AggregateOfferSchema } from 'schemaorg-kit';

const product = createProduct({
  name: 'Trail Runner Pro',
  offers: AggregateOfferSchema.parse({
    lowPrice: 89.99,
    highPrice: 149.99,
    priceCurrency: 'USD',
    offerCount: 12,
    availability: 'InStock',
  }),
});

OfferShippingDetailsSchema / DefinedRegionSchema / ShippingDeliveryTimeSchema

import {
  OfferShippingDetailsSchema,
  DefinedRegionSchema,
  ShippingDeliveryTimeSchema,
  type OfferShippingDetails,
  type DefinedRegion,
  type ShippingDeliveryTime,
} from 'schemaorg-kit';

Required for Google’s Merchant Listing shipping eligibility. Add shippingDetails to Offer on a product page.

OfferShippingDetailsSchema fields

Field Type Notes
shippingRate { value, currency }? Shipping cost (use value: 0 for free)
shippingDestination DefinedRegion \| DefinedRegion[]? Where it ships
deliveryTime ShippingDeliveryTime? How long it takes
doesNotShip boolean? Explicitly mark no-ship regions
shippingLabel string? Display label, e.g. "Free shipping"

DefinedRegionSchema fields

Field Type Notes
addressCountry string? ISO 3166-1 alpha-2 country code
addressRegion string \| string[]? State/province codes
postalCodePrefix string \| string[]? Zip code prefix(es)
postalCodeRange { postalCodeBegin, postalCodeEnd }? Zip range

ShippingDeliveryTimeSchema fields

Field Type Notes
handlingTime { minValue, maxValue, unitCode: "DAY" }? Days to process order
transitTime { minValue, maxValue, unitCode: "DAY" }? Days in transit
cutoffTime string? Order cutoff, e.g. "14:00:00"

Example — Free US shipping

import { createProduct, OfferShippingDetailsSchema, DefinedRegionSchema, ShippingDeliveryTimeSchema } from 'schemaorg-kit';

const product = createProduct({
  name: 'Trail Runner Pro',
  offers: {
    '@type': 'Offer',
    price: 129.99,
    priceCurrency: 'USD',
    availability: 'InStock',
    shippingDetails: OfferShippingDetailsSchema.parse({
      shippingLabel: 'Free Standard Shipping',
      shippingRate: { value: 0, currency: 'USD' },
      shippingDestination: DefinedRegionSchema.parse({ addressCountry: 'US' }),
      deliveryTime: ShippingDeliveryTimeSchema.parse({
        handlingTime: { minValue: 0, maxValue: 1 },
        transitTime: { minValue: 3, maxValue: 7 },
        cutoffTime: '14:00:00',
      }),
    }),
  },
});

MerchantReturnPolicySchema

import { MerchantReturnPolicySchema, type MerchantReturnPolicy } from 'schemaorg-kit';

Used on Organization.hasMerchantReturnPolicy and Product.hasMerchantReturnPolicy to improve Product rich result eligibility.

Fields

Field Type Notes
applicableCountry string \| string[]? ISO 3166-1 alpha-2
returnPolicyCategory string? Schema.org enum URL
merchantReturnDays number? Days allowed for returns
returnMethod string? Schema.org enum URL
returnFees string? Schema.org enum URL
refundType string? Schema.org enum URL
merchantReturnLink string? URL to return policy page
returnShippingFeesAmount MonetaryAmount? Shipping cost for returns
itemCondition ItemCondition \| []? Condition(s) eligible for return
returnLabelSource string? Schema.org enum URL
returnPolicyCountry string? ISO 3166-1 alpha-2
restockingFee MonetaryAmount \| number? Restocking fee
returnPolicySeasonalOverride SeasonalOverride \| []? Holiday return window
customerRemorseReturnFees string? Buyer’s remorse return fees
itemDefectReturnFees string? Defective item return fees
const returnPolicy = MerchantReturnPolicySchema.parse({
  applicableCountry: ['US', 'CA', 'GB'],
  returnPolicyCategory: 'https://schema.org/MerchantReturnFiniteReturnWindow',
  merchantReturnDays: 30,
  returnMethod: 'https://schema.org/ReturnByMail',
  returnFees: 'https://schema.org/FreeReturn',
  merchantReturnLink: 'https://example.com/returns',
  returnPolicySeasonalOverride: {
    '@type': 'MerchantReturnPolicySeasonalOverride',
    startDate: '2025-11-15',
    endDate: '2026-01-31',
    returnPolicyCategory: 'https://schema.org/MerchantReturnFiniteReturnWindow',
    merchantReturnDays: 60,
  },
});

OpeningHoursSpecificationSchema

import { OpeningHoursSpecificationSchema, type OpeningHoursSpecification } from 'schemaorg-kit';

Used with LocalBusiness.openingHoursSpecification and LocalBusiness.specialOpeningHoursSpecification.

import { OpeningHoursSpecificationSchema } from 'schemaorg-kit';

// Regular hours
const weekdays = OpeningHoursSpecificationSchema.parse({
  dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
  opens: '09:00:00',
  closes: '17:00:00',
});

// Special holiday hours (use specialOpeningHoursSpecification)
const holiday = OpeningHoursSpecificationSchema.parse({
  dayOfWeek: 'Thursday',
  opens: '00:00:00',   // midnight to midnight = closed
  closes: '00:00:00',
  validFrom: '2025-12-25',
  validThrough: '2025-12-25',
});

Valid dayOfWeek values: "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "PublicHolidays"


HowToStepSchema / HowToSectionSchema

import { HowToStepSchema, HowToSectionSchema } from 'schemaorg-kit';

For Recipe.recipeInstructions and HowTo types.

// Simple step
const step = HowToStepSchema.parse({
  name: 'Preheat',
  text: 'Preheat oven to 350°F (175°C).',
  url: 'https://example.com/recipe#step-1',
  image: 'https://example.com/recipe/step-1.jpg',
});

// Section with sub-steps
const section = HowToSectionSchema.parse({
  name: 'Prepare the sauce',
  itemListElement: [
    { '@type': 'HowToStep', text: 'Dice the tomatoes.' },
    { '@type': 'HowToStep', text: 'Sauté garlic in olive oil.' },
    { '@type': 'HowToStep', text: 'Add tomatoes and simmer for 20 minutes.' },
  ],
});

PersonOrOrgRef

import { PersonOrOrgRef, type PersonOrOrgRefType } from 'schemaorg-kit';

A union type used for fields that accept either a Person or an Organization. Accepts:

  • A URL string (reference by URL)
  • A { "@type": "Person", ... } object
  • A { "@type": "Organization", ... } object

Used on: author, publisher, creator, contributor, copyrightHolder, hiringOrganization, etc.

// All of these are valid:
{ author: 'https://example.com/authors/alice' }          // URL reference
{ author: { '@type': 'Person', name: 'Alice' } }          // Person object
{ author: { '@type': 'Organization', name: 'Acme' } }     // Org object
{ author: createPerson({ name: 'Alice' }).toObject() }     // From factory

ClipSchema / BroadcastEventSchema / SeekToActionSchema / VideoObjectSchema

See Creative Works → createVideoObject.


InteractionCounterSchema

import { InteractionCounterSchema, type InteractionCounter } from 'schemaorg-kit';

Tracks user interactions (likes, shares, views, etc.). Used on VideoObject.interactionStatistic, DiscussionForumPosting.interactionStatistic, Person.interactionStatistic, and Organization.interactionStatistic.

Field Type Notes
interactionType string Required — Full URL, e.g. "https://schema.org/LikeAction"
userInteractionCount number Required — Non-negative integer
const counter = InteractionCounterSchema.parse({
  interactionType: 'https://schema.org/WatchAction',
  userInteractionCount: 1250000,
});

Common interaction types: LikeAction, ShareAction, WatchAction, CommentAction, FollowAction, WriteAction


MemberProgramSchema / MemberProgramTierSchema

import { MemberProgramSchema, MemberProgramTierSchema, type MemberProgram } from 'schemaorg-kit';

For Google’s Merchant Listing loyalty program support. Used on Organization.hasMemberProgram.

MemberProgramTierSchema fields

Field Type Notes
name string Required — Tier name, e.g. “Gold”
hasTierBenefit string \| string[] Required — Benefit names
hasTierRequirement string \| object? Requirements to reach this tier
membershipPointsEarned QuantitativeValue? Points earned per purchase
url string? Tier details page

MemberProgramSchema fields

Field Type Notes
name string Required — Program name
description string? Program description
hasTiers MemberProgramTier \| []? Loyalty tiers
url string? Program page URL
const loyaltyProgram = MemberProgramSchema.parse({
  name: 'Acme Rewards',
  description: 'Earn points on every purchase.',
  url: 'https://acme.com/rewards',
  hasTiers: [
    MemberProgramTierSchema.parse({
      name: 'Silver',
      hasTierBenefit: ['Free shipping on orders over $25'],
    }),
    MemberProgramTierSchema.parse({
      name: 'Gold',
      hasTierBenefit: ['Free shipping on all orders', '10% member discount'],
      membershipPointsEarned: { '@type': 'QuantitativeValue', value: 2, unitText: 'points per dollar' },
    }),
  ],
});

ShippingServiceSchema / ShippingConditionsSchema / ServicePeriodSchema

import {
  ShippingServiceSchema,
  ShippingConditionsSchema,
  ServicePeriodSchema,
  type ShippingService,
} from 'schemaorg-kit';

Organization-level shipping service definitions for Google Merchant Listings. Used on Organization.hasShippingService.

ShippingServiceSchema fields

Field Type Notes
name string? Service name, e.g. “Standard Shipping”
description string? Service description
shippingConditions ShippingConditions \| []? Rate/region/time rules
handlingTime ServicePeriod? Business-day handling window
fulfillmentType string? "Delivery", "Pickup", "DigitalDelivery"
validForMemberTier string \| object? Restrict to a loyalty tier

ShippingConditionsSchema fields

Field Type Notes
shippingRate MonetaryAmount? Shipping cost
shippingDestination DefinedRegion \| []? Where it ships
shippingOrigin DefinedRegion \| []? Where it ships from
deliveryTime ShippingDeliveryTime? Handling + transit time
doesNotShip boolean? Explicitly mark no-ship
orderValue MonetaryAmount? Minimum order value
numItems QuantitativeValue? Item count constraint
weight QuantitativeValue? Weight constraint

ServicePeriodSchema fields

Field Type Notes
businessDays OpeningHoursSpecification? Which days orders are processed
cutoffTime string? ISO 8601 time, e.g. "14:00:00-05:00"
duration string? ISO 8601 duration, e.g. "P3D"
import { createOrganization, ShippingServiceSchema, ShippingConditionsSchema } from 'schemaorg-kit';

const org = createOrganization({
  name: 'Acme Store',
  hasShippingService: ShippingServiceSchema.parse({
    name: 'Free Standard Shipping',
    fulfillmentType: 'Delivery',
    shippingConditions: ShippingConditionsSchema.parse({
      shippingRate: { '@type': 'MonetaryAmount', currency: 'USD', value: 0 },
      shippingDestination: { '@type': 'DefinedRegion', addressCountry: 'US' },
      deliveryTime: {
        '@type': 'ShippingDeliveryTime',
        transitTime: { '@type': 'QuantitativeValue', minValue: 3, maxValue: 7 },
      },
    }),
  }),
});