A buyer walks into your agency with a wish list: three bedrooms, garden, max budget €250,000, northeast area. Three weeks later, you haven't shown them anything relevant. They've already gone to a competitor. The problem isn't a lack of listings — it's the absence of a system that automatically matches demand with supply. We, at Meteora Web, see this every day in the management software we build: automatic matching isn't a luxury; it's the engine that turns a database into sales.
In this guide we show you how to build a matching system that really works: the logic behind it, clean data, and a few lines of code that make all the difference.
How does automatic property matching work?
Automatic matching is a software process that compares a client's search criteria (request) with the features of every property in the archive and calculates a similarity score. The system then presents the best-matching properties to the agent, or sends an automatic notification to the client if the score exceeds a threshold.
Sponsored Protocol
The basic logic is simple: the more criteria match, the higher the score. But simplicity ends there. In practice, criteria have different weights: location is almost always more important than number of bathrooms. A budget overshoot of 5% may be negotiable; a ground-floor apartment without an elevator for a client with reduced mobility is a hard no.
Here's a typical rule structure we use in our projects:
- Blocking criteria (direct exclusion): max budget, property type (apartment vs villa), mandatory zone. If they don't match, the property is discarded immediately.
- Weighted criteria (scoring): surface area, number of rooms, floor, elevator, garden, parking, construction year, energy class.
- Bonus criteria (multipliers): exact same district, immediate availability, price below budget.
A common mistake is treating all criteria equally. We always start with historical data analysis: which features actually led to a sale? Those become the dominant weights.
What makes a difference compared to a simple filter?
A traditional filter (e.g. "house with garden AND budget < 250k") returns zero results even if there is a property with garden at 255k. A scoring system would still show it with a slightly lower score, leaving the decision to the agent. That's what sells more.
Sponsored Protocol
Operational example: Take a real client request: three-room apartment, 80-100 sqm, historic center, budget €200,000. The database has two properties:
- Property A: three-room, 85 sqm, historic center, €195,000 → score 100%
- Property B: three-room, 90 sqm, 500 m from historic center (adjacent area), €210,000 → score 75% (loses on zone and exceeds budget by 5%)
With a boolean filter, B would never be proposed. With weighted matching, the agent sees B and can evaluate if the client would accept the adjacent area in exchange for 5 additional sqm. Often it works.
What data do you need for effective matching?
Automatic matching is only as good as the data feeding it. If the property archive has empty fields, inconsistent data, or different formats, the system produces unreliable results. We learned this the hard way managing the ERP of a clothing store: without clean inventory data, stock levels were wrong and customer orders were lost. For property matching it's the same.
Sponsored Protocol
Here is the minimum checklist of fields every property must have structured:
- Address or geographic coordinates (lat/lon or zone polygons)
- Type (apartment, villa, penthouse, loft, etc.) – use a closed taxonomy, not free text
- Surface area in sqm, with acceptable tolerance (e.g. ±10%)
- Number of bedrooms and bathrooms
- Floor and elevator availability
- Energy class (A4 to G)
- Asking price and minimum accepted price (for negotiation)
- Availability date
- Extra features (garden, parking, terrace, air conditioning, furnished, etc.) – normalized as boolean flags
On the client request side, you need the same fields plus a flexibility degree for each parameter (e.g. "budget up to 220k", "zone also adjacent", "ground floor or first floor").
How to normalize geographic data for zone matching
Zone is often the most important criterion. A robust way to handle it is to assign each property a hierarchical zone code (neighborhood → macrozone → city) and match not only on the exact zone but also on adjacent ones with reduced weight. In SQL, you can use an adjacency table:
Sponsored Protocol
-- Zone adjacency table
CREATE TABLE zone_adjacencies (
zone_id INT,
adjacent_zone_id INT,
weight DECIMAL(3,2) DEFAULT 0.5 -- weight for match on adjacent zone
);
-- Match query: returns properties in requested zone or adjacent
SELECT p.*,
CASE WHEN p.zone_id = r.zone_id THEN 1.0
ELSE COALESCE(za.weight, 0)
END AS zone_weight
FROM properties p
JOIN requests r ON ...
LEFT JOIN zone_adjacencies za ON p.zone_id = za.adjacent_zone_id
AND r.zone_id = za.zone_id
WHERE p.price <= r.budget_max * 1.1; -- 10% tolerance
This approach is simple, fast, and maintainable. For even more precision, integrate a geocoding service (e.g. Google Maps API) and calculate distance in meters between two points.
How to implement a matching system without mistakes?
The most common mistake is thinking that a ready-made software will do the job. In reality, automatic matching requires continuous evolution: weights need calibration on real data, cutoff thresholds need testing, and agent feedback (why was a match discarded?) must be logged to improve the algorithm.
Sponsored Protocol
We, at Meteora Web, built a proprietary platform for managing multiple clients (not real estate, but the logic is similar). The key point was making the score visible to the operator: the agent must understand why that score is 75 and not 100. Without transparency, the system gets ignored.
Basic weighted scoring algorithm (pseudocode)
def calculate_score(property, request):
score = 0
total_weight = 0
# Blocking criteria: if not passed, return 0
if property.price > request.budget_max * (1 + request.price_tolerance):
return 0
if property.type not in request.accepted_types:
return 0
# ... other blocking criteria
# Weighted criteria
criteria = [
(property.surface, request.surface_min, request.surface_max, 20),
(property.bedrooms, request.bedrooms_min, request.bedrooms_max, 15),
(property.floor, request.floor_min, request.floor_max, 10),
(request.elevator_required, property.elevator, 10), # boolean
(request.garden_required, property.garden, 5),
# ... add more
]
for value, min_val, max_val, weight in criteria:
if min_val <= value <= max_val:
score += weight
elif value < min_val:
score += weight * (value / min_val) # proportional penalty
else:
score += weight * (max_val / value)
total_weight += weight
# Bonus: exact zone
if property.zone == request.zone:
score += 30
total_weight += 30
return (score / total_weight) * 100 if total_weight > 0 else 0
Note: This is a didactic example. In production, also handle geographic distance, availability date, and use weights normalized against historical conversion data.
Data quality is the real bottleneck
If a property has the field "surface" written as "100 sqm" and another as "100", numeric comparison fails. We've seen cases where 40% of properties had empty or inconsistent fields. Without cleaning, any algorithm is useless.
Monthly data quality checklist:
- Check that all numeric fields are actually numeric and not text
- Validate outliers (e.g. price of 1,000,000,000 for a studio)
- Ensure zones are coded exactly the same way (use a dropdown, not an open input)
- Set mandatory fields for at least 8 core features
What tools to use for implementing matching?
You don't need artificial intelligence. Good SQL, a backend in PHP or Python, and some logic are enough. If you use an existing real estate CRM, check if it exposes webhooks or APIs to read properties and requests. We have integrated systems with Laravel + Livewire for the UI and SQL code for batch matching.
If you prefer an off-the-shelf solution, consider platforms like Rethink or Luxury Presence (for the US market), but watch out for recurring costs and data ownership. As we always say: owning your stack beats renting it.
For those who want to dive deeper into vector-based matching (cosine similarity), we recommend the official documentation of scikit-learn cosine_similarity – useful if you have many categorical attributes to compare.
What to do next
- Audit existing data: Export all property listings and check field completeness and consistency. Create a missing fields report.
- Define blocking criteria and weights with your sales team: what makes a property absolutely not proposable? What are the top 3 factors that matter most to your typical clients?
- Build a scoring prototype on a subset of data (e.g. only 50 properties and 10 requests). Manually test results with agents.
- Collect feedback for every non-accepted match: "why didn't you call the client for this property?" Log the reason and adjust weights.
- Automate the process with a notification (email or push) to the agent when a new property scores > 80% against an open request.
Automatic matching is not magic: it's data discipline and well-calibrated logic. We, at Meteora Web, have been applying it for years in the software we develop for agencies and retailers. If you want to see it in action in a real context, check our page dedicated to real estate software.
Zenith Real Estate is the all-in-one platform to run your business — clients, scheduling, deadlines, invoicing and WhatsApp reminders, all from your browser. No installation required.
Discover Zenith Real Estate →