Most property listings are invisible to AI search. This guide shows you why, and how to fix it, whether you list 1 property or 10,000.
JSON-LD schema markup, structured data, and location enrichment to make property listings visible in ChatGPT, Perplexity, and Google AI Overviews.
Without geo data
What AI sees: nothing matchable. Zero neighbourhood or proximity queries answered.
With GeoEnrich
What AI sees: matchable for 50+ query types including "2-bedroom near tram in De Pijp", "apartment with parking under 400k", "quiet street close to schools".
GeoEnrich generates the right column automatically from an address. One API call.
Add this JSON-LD to your property listing page and AI search engines can immediately parse and recommend it:
{
"@context": "https://schema.org",
"@type": "RealEstateListing",
"name": "2-Bedroom Apartment in Amsterdam De Pijp",
"url": "https://www.example-agency.com/listings/ruysdaelkade-21",
"description": "Bright 2-bedroom apartment on the Ruysdaelkade in De Pijp, Amsterdam. 85 square meters, south-facing balcony, open-plan kitchen, renovated bathroom. 200 meters from Albert Cuyp market, 1-minute walk to tram lines 3 and 12.",
"datePosted": "2026-03-15",
"about": {
"@type": "Residence",
"address": {
"@type": "PostalAddress",
"streetAddress": "Ruysdaelkade 21",
"addressLocality": "Amsterdam",
"addressRegion": "North Holland",
"postalCode": "1072 AK",
"addressCountry": "NL"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 52.3534,
"longitude": 4.8965
},
"floorSize": {
"@type": "QuantitativeValue",
"value": 85,
"unitCode": "MTK"
},
"numberOfRooms": 3,
"numberOfBedrooms": 2,
"numberOfBathroomsTotal": 1,
"petsAllowed": false,
"yearBuilt": "1925"
},
"offers": {
"@type": "Offer",
"price": 395000,
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock"
}
}
This covers the basics. The sections below explain how to add neighbourhood context, nearby POIs, transit data, and more to make your listings match dozens of additional query types. See the schema examples tab for complete, production-ready files.
Property searches through AI are fundamentally different from portal searches. Instead of filtering dropdowns, people describe what they want in natural language. Understanding these intent patterns is the foundation of real estate GEO.
These are the most common property queries and the hardest for traditional listings to answer:
Every one of these queries requires structured location data, coordinates, and nearby POI context. Without it, your listing is invisible.
Buyers and renters care about what is nearby. AI engines need distance data to answer:
These combine property attributes with location:
Investors ask different questions:
To appear in any of these results, your listing needs structured data that AI engines can parse: exact coordinates, nearby POIs with distances, property specifications as structured fields, and neighbourhood context signals.
The vast majority of property listings are invisible to AI search engines. Here is why, and what to fix.
"Located in a desirable neighbourhood" tells AI nothing. "Ruysdaelkade 21, Amsterdam De Pijp, 200 meters from Albert Cuyp market" tells AI everything. Vague descriptions are the single biggest reason listings fail. AI cannot infer that "great area" means De Pijp, or that "close to shops" means 200 meters from a market.
Without latitude and longitude, AI cannot calculate distances. Every proximity query ("near the park", "close to metro", "walking distance to schools") requires coordinates on both the listing and the POI. Coordinates must be precise to 4+ decimal places. "52.35, 4.90" points to a 100-meter radius; "52.3534, 4.8965" points to a specific building.
This is where most listings fail even if they have an address. A listing with coordinates but no nearby POI data cannot answer "apartments near schools" because AI has no school data to match against. You need to explicitly state what is nearby, with names and distances.
Property details buried in paragraph text are hard for AI to extract. "This lovely 85m2 apartment has 2 bedrooms, 1 bathroom, and a south-facing balcony" is human-readable. But structured schema fields like floorSize: 85, numberOfBedrooms: 2, and amenityFeature: "South-facing balcony" are machine-readable. AI engines strongly prefer structured data.
A listing posted 6 months ago with no datePosted or dateModified field looks abandoned. AI engines deprioritise content that appears outdated. Always include dates and update them when the listing changes.
Price buried in text ("asking price: EUR 395,000") is harder to parse than an Offer with price: 395000 and priceCurrency: "EUR". Price is one of the most common filters in property queries, so missing structured pricing means missing those queries entirely.
The RealEstateListing type from Schema.org is the correct schema for property listings. It wraps a property (Residence, Apartment, House) inside a listing context with price, date, and availability.
A RealEstateListing has three key parts:
about): address, geo, floorSize, numberOfRooms, amenitiesUse the most specific @type for the property inside about:
Apartment for flats, condos, studio apartmentsHouse or SingleFamilyResidence for detached/semi-detached housesResidence as a general fallbackThese fields are the minimum for AI discoverability:
{
"@context": "https://schema.org",
"@type": "RealEstateListing",
"name": "Descriptive title with key features and location",
"description": "150-300 word description with specific details",
"datePosted": "2026-03-15",
"about": {
"@type": "Apartment",
"address": {
"@type": "PostalAddress",
"streetAddress": "Herengracht 100",
"addressLocality": "Amsterdam",
"addressRegion": "North Holland",
"postalCode": "1015 BS",
"addressCountry": "NL"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 52.3728,
"longitude": 4.8882
},
"floorSize": {
"@type": "QuantitativeValue",
"value": 120,
"unitCode": "MTK"
},
"numberOfRooms": 5,
"numberOfBedrooms": 3,
"numberOfBathroomsTotal": 2
},
"offers": {
"@type": "Offer",
"price": 650000,
"priceCurrency": "EUR"
}
}
These fields increase the number of queries your listing can match:
yearBuilt: construction year (important for renovation queries)petsAllowed: true/false (filters pet-friendly searches)amenityFeature: array of features like "Balcony", "Parking", "Garden", "Elevator", "Storage"numberOfFullBathrooms / numberOfPartialBathrooms: more specific than totalfloorLevel: which floor the property is onpermittedUsage: "Residential", "Mixed-use", "Commercial"Coordinates alone tell AI where a property is. Geo enrichment tells AI what is around it. This is the difference between matching 5 query types and matching 50.
For a property at Ruysdaelkade 21 in Amsterdam, geo enrichment provides:
Use the additionalProperty field on the property to add nearby context:
{
"@type": "Apartment",
"address": {
"@type": "PostalAddress",
"streetAddress": "Ruysdaelkade 21",
"addressLocality": "Amsterdam",
"postalCode": "1072 AK",
"addressCountry": "NL"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 52.3534,
"longitude": 4.8965
},
"additionalProperty": [
{
"@type": "PropertyValue",
"name": "Nearest School",
"value": "De Pijp Primary School, 350m"
},
{
"@type": "PropertyValue",
"name": "Nearest Supermarket",
"value": "Albert Heijn, 150m"
},
{
"@type": "PropertyValue",
"name": "Nearest Tram Stop",
"value": "Tram 3 (Ruysdaelkade), 80m"
},
{
"@type": "PropertyValue",
"name": "Nearest Park",
"value": "Sarphatipark, 400m"
},
{
"@type": "PropertyValue",
"name": "Nearest Hospital",
"value": "OLVG Hospital, 800m"
},
{
"@type": "PropertyValue",
"name": "Restaurants within 500m",
"value": "23"
}
]
}
Without this data, AI cannot answer any of these queries about your listing:
The MapAtlas GeoEnrich API generates all of this from a single address or coordinate pair. One API call returns schools, transit, shopping, parks, healthcare, and restaurants with names and distances, ready to embed as additionalProperty values.
Beyond individual POIs, buyers and renters want to understand the neighbourhood itself. AI engines look for signals that describe the character and livability of an area.
Neighbourhood-level scores help AI answer lifestyle queries:
{
"additionalProperty": [
{
"@type": "PropertyValue",
"name": "Walk Score",
"value": "92/100"
},
{
"@type": "PropertyValue",
"name": "Transit Score",
"value": "88/100"
},
{
"@type": "PropertyValue",
"name": "Bike Score",
"value": "95/100"
}
]
}
These scores directly answer queries like "walkable neighbourhoods in Amsterdam for car-free living" or "best areas for cycling commuters in Amsterdam."
Commute time is one of the top decision factors for property buyers. Include it as structured data:
{
"@type": "PropertyValue",
"name": "Commute to Amsterdam Centraal",
"value": "12 minutes by tram, 18 minutes by bike"
}
Your listing description should include neighbourhood context. Instead of "great neighbourhood", write:
"De Pijp is one of Amsterdam's most sought-after neighbourhoods, known for the Albert Cuyp street market, a diverse restaurant scene, and tree-lined canals. The area has excellent public transport with tram lines 3, 12, and 24, plus the recently opened Metro 52 (North-South line). Sarphatipark offers green space within 400 meters."
This paragraph alone matches dozens of AI queries because it contains specific, verifiable facts that AI can extract and cite.
Aggregate counts give AI a sense of density and convenience:
These counts enable comparison queries: "Which Amsterdam neighbourhood has the most restaurants nearby?" or "Areas with the best school coverage."
Rental and sale listings use the same RealEstateListing wrapper, but the offer structure and some property fields differ.
{
"offers": {
"@type": "Offer",
"price": 395000,
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock",
"validFrom": "2026-03-15"
}
}
For rentals, the price represents monthly rent. Use priceSpecification to clarify the billing period:
{
"offers": {
"@type": "Offer",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": 1850,
"priceCurrency": "EUR",
"unitText": "MONTH"
},
"availability": "https://schema.org/InStock"
}
}
Rental listings benefit from additional fields that sale listings do not need:
leaseLength: minimum lease duration (e.g., 12 months)petsAllowed: critical for rental searches ("pet-friendly rentals in Amsterdam")amenityFeature: furnished/unfurnished, included utilities, parkingvalidFrom on the Offer)Short-term holiday rentals (Airbnb-style) should not use RealEstateListing. They use LodgingBusiness with nightly pricing and check-in/check-out times. See the vacation rental section below for details.
Commercial property searches follow different patterns than residential. Businesses searching for office, retail, or industrial space ask questions that require specific structured data.
Use specific types where possible:
OfficeBuilding for office spaceShoppingCenter or Store for retailWarehouse for industrial/logisticsLocalBusiness as a general fallback with additionalTypeCommercial listings need fields that residential ones do not:
{
"@context": "https://schema.org",
"@type": "RealEstateListing",
"name": "350m2 Office Space in Amsterdam Zuidas",
"about": {
"@type": "OfficeBuilding",
"address": {
"@type": "PostalAddress",
"streetAddress": "Barbara Strozzilaan 201",
"addressLocality": "Amsterdam",
"postalCode": "1083 HN",
"addressCountry": "NL"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 52.3361,
"longitude": 4.8756
},
"floorSize": {
"@type": "QuantitativeValue",
"value": 350,
"unitCode": "MTK"
},
"amenityFeature": [
{"@type": "LocationFeatureSpecification", "name": "Fiber Internet"},
{"@type": "LocationFeatureSpecification", "name": "24/7 Access"},
{"@type": "LocationFeatureSpecification", "name": "Meeting Rooms"},
{"@type": "LocationFeatureSpecification", "name": "Parking Garage"},
{"@type": "LocationFeatureSpecification", "name": "Reception Desk"}
],
"additionalProperty": [
{"@type": "PropertyValue", "name": "Floor Level", "value": "8th floor"},
{"@type": "PropertyValue", "name": "Nearest Metro", "value": "Amsterdam Zuid, 200m"},
{"@type": "PropertyValue", "name": "Parking Spaces", "value": "12 included"}
]
},
"offers": {
"@type": "Offer",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": 45,
"priceCurrency": "EUR",
"unitText": "SQM/YEAR"
}
}
}
Commercial tenants care about different nearby context than residents:
The GeoEnrich API returns all of these POI categories, so you can automatically enrich commercial listings with the context that business tenants search for.
Vacation rentals (Airbnb-style short stays) need a completely different schema approach. These are hospitality businesses, not property sales or long-term rentals.
The correct schema type for vacation rentals is LodgingBusiness (or the more specific VacationRental if supported). This tells AI engines that the property accepts short-term guests with nightly pricing, check-in/out times, and hospitality amenities.
Holiday rental searches are highly specific:
{
"@context": "https://schema.org",
"@type": "LodgingBusiness",
"name": "Canal View Apartment in Amsterdam Jordaan",
"description": "Charming 1-bedroom canal house apartment in the heart of Jordaan. Sleeps 2 guests. Original wooden beams, modern kitchen, rain shower. 5-minute walk to Anne Frank House and Westerkerk. Free WiFi, Smart TV, Nespresso machine.",
"address": {
"@type": "PostalAddress",
"streetAddress": "Prinsengracht 263",
"addressLocality": "Amsterdam",
"postalCode": "1016 GV",
"addressCountry": "NL"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 52.3752,
"longitude": 4.8839
},
"checkinTime": "15:00",
"checkoutTime": "11:00",
"numberOfRooms": 1,
"petsAllowed": false,
"amenityFeature": [
{"@type": "LocationFeatureSpecification", "name": "Free WiFi"},
{"@type": "LocationFeatureSpecification", "name": "Kitchen"},
{"@type": "LocationFeatureSpecification", "name": "Washing Machine"},
{"@type": "LocationFeatureSpecification", "name": "Smart TV"},
{"@type": "LocationFeatureSpecification", "name": "Air Conditioning"},
{"@type": "LocationFeatureSpecification", "name": "Canal View"}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.8,
"reviewCount": 127,
"bestRating": 5
},
"offers": {
"@type": "Offer",
"price": 135,
"priceCurrency": "EUR",
"unitText": "NIGHT"
}
}
Vacation rental guests care about different nearby POIs than long-term residents:
Use the GeoEnrich API to automatically generate tourist-relevant POI data for each vacation rental listing.
Follow this process to implement schema markup across your property listings.
Place the <script type="application/ld+json"> tag in the <head> of each listing page. For property portals with thousands of listings, generate the schema server-side from your listing database.
Test each schema with these tools:
After deployment, ask AI engines about your listings:
If AI cannot answer with specifics, your schema is incomplete or not being crawled. Check that your page is indexable (no noindex tag), the JSON-LD is in the rendered HTML (not just client-side JS), and your sitemap includes listing pages.
The checklist tab on this page covers every field and signal needed for complete property listing GEO. Work through each section systematically. Aim for 100% completion on the basic schema and address sections, then add nearby context and neighbourhood signals for maximum coverage.
Manually adding nearby POIs, transit data, and neighbourhood context to every listing is not feasible at scale. If you manage 100+ properties, you need automation.
The MapAtlas GeoEnrich API takes an address or coordinate pair and returns structured nearby context:
The typical workflow for property portals:
additionalProperty valuesThis process runs automatically for every new listing and can be batch-processed for existing inventory.
Without GeoEnrich, a listing matches queries about its address and basic specs (bedrooms, price). With GeoEnrich, the same listing matches queries about schools, transit, walkability, nearby restaurants, parks, hospitals, and commute times. That is the difference between matching 5 query types and 50+.
For implementation details and API documentation, see the GeoEnrich API page.
Automate this at scale
The MapAtlas GeoEnrich API adds coordinates, nearby POIs, transit access, neighbourhood context, and schema-ready geo data to every listing automatically, one API call per listing, at any scale.