Dream Estate Immobilien
A complete real-estate website for a German estate agent — designed, built, optimised and made legally compliant.

| Client | Dream Estate Immobilien — independent estate agent |
| Market | Baden-Baden, Achern and the Ortenau region, Germany |
| Scope | Full site design & build, custom listings system, performance, SEO, GDPR compliance |
| Timeline | September 2026 |
| Stack | WordPress · Elementor · custom PHP plugin · Contact Form 7 · Rank Math |
| Language | German (de_DE) |
The brief
An independent estate agent launching in Baden-Baden needed a website that could do three things at once: look like the premium property brands she competes with, let her manage her own listings and content without calling a developer, and satisfy German data-protection law from day one.
She had a static HTML template she liked. Everything else — the content, the listings system, the compliance layer, the performance work — had to be built.
What I built
A 13-page site, fully editable
Homepage, About, Sell your property, Free valuation, Contact, Referral programme, Guide, Property listings, plus five legal pages. Every page is a real Elementor layout — the owner can edit any heading, image or section herself.

A custom property-listings plugin
Rather than bending a generic real-estate theme to fit, I wrote a purpose-built WordPress plugin:
- A
propertycontent type with flat, German-named fields (price, town, rooms, bathrooms, living area, plot, year, status) — deliberately structured so an OpenImmo feed, the German property-data standard, can be mapped onto it later without a rebuild. - A filterable listings overview: search, property type, town, status, minimum rooms, minimum area, and sorting.
- Detail pages with specification tables, a viewing-request form and related properties.
- Homepage grids that stay in sync automatically — newest listings, "featured" listings, and a "view more" button that appears once there are more than four.


Lead capture throughout
Six forms feed the agent's pipeline — quick valuation on the homepage, a detailed valuation questionnaire, contact, viewing requests, a referral programme and a newsletter. Each one carries an explicit, unticked consent checkbox linked to the privacy policy, as German law requires.

Content that sells the service
I wrote the full German copy: service pages that explain the process without jargon, a four-article guide section on valuation, timing, common mistakes and how long a sale takes, and a referral programme page.


Mobile
The site is built mobile-first in practice, not just in theory: a single-row header with the logo and a hamburger, and a slide-in menu that locks the page behind it and returns the visitor to exactly where they were.
Results
Measured with Lighthouse against uncached pages — the worst case a real visitor sees.
| Before | After | |
|---|---|---|
| Page weight (mobile) | 13.47 MB | 0.25 MB |
| Page weight (desktop) | 14.04 MB | 3.48 MB |
| Largest Contentful Paint | 4.4 s | 1.8 s |
| Requests (mobile) | 49 | 31 |
| Stylesheets | 21 files | 4 files |
| Render-blocking CSS | 15 | 3 |
Lighthouse
| Performance | Accessibility | Best Practices | SEO |
|---|---|---|---|
| 95–96 mobile · 93–98 desktop | 100 | 100 | 100 |
A 98% reduction in mobile page weight matters commercially here: property buyers browse on phones, often on mobile data, and a 13 MB page loses them before the first listing appears.
How the performance was won
- Every image converted to WebP, capped at sensible dimensions — 4.84 MB down to 0.28 MB.
- The hero video re-encoded from 10.18 MB to 3.05 MB and re-engineered to load after the page is usable, and not at all on reduced-data connections. It had also been downloading three times over because of a conflict between the autoplay attribute and the lazy-loading script — a bug that only showed up by inspecting the network log.
- Dead weight removed: two icon-font libraries serving zero icons (the site uses inline SVG), a 318 KB webfont nothing used, and legacy jQuery shims.
- Critical CSS inlined, the rest left cacheable — 15 render-blocking requests down to 3.
- The largest element preloaded per device: the video poster on desktop, the headline font on mobile.
German compliance, designed in rather than bolted on
For a German site this is a legal requirement, not a nicety — and it's where most WordPress builds quietly fail.
Consent that actually works. A full consent manager with accept all, reject all, customise, and a dismiss that returns on the next visit. Crucially, embedded third-party content is blocked server-side — the Google Maps iframe leaves the server with no source address at all, so nothing can leak if a script fails.

A map that respects privacy without looking broken. Embedding Google Maps sends every visitor's IP address to Google before they agree to anything. Blocking it leaves an empty grey box where the map should be — so visitors never find the office.
My solution: a real map, generated from OpenStreetMap data and hosted on the client's own server, with working zoom controls and a gold pin on the office. Nothing is requested from any third party. One button opens the location in Google Maps in a new tab (the visitor choosing to leave, which needs no consent); another loads the live interactive map in place with a single click.

Self-hosted fonts. Loading fonts from Google's servers has been ruled unlawful in Germany without consent. All fonts are served from the client's own domain.
Deliverability. I found that enquiry emails were being sent from an address whose domain publishes a strict anti-spoofing policy the server couldn't satisfy — meaning enquiries would have been silently spam-filtered. Fixed before launch.
SEO
- Hand-written German titles, meta descriptions and focus keywords for all 23 indexable URLs — unique, within Google's display limits, each naming the service area.
- Listings generate their own metadata from their property fields, so a new listing is optimised the moment it's published.
RealEstateAgentstructured data with address, opening hours and coordinates — the data behind local search results and Google Maps.- XML sitemaps, and thin pages (search results, tag archives, attachment pages) correctly kept out of the index.
Result: 100/100 Lighthouse SEO, with every page audited for title length, description length, canonical correctness, heading structure and robots directives.
Accessibility
100/100, including fixes that needed real digging:
- Elementor's accordion applied button behaviour to a heading element and used links with no destination — invalid markup that confuses screen readers. I rebuilt it with correct semantics, verified by keyboard as well as mouse.
- The brand gold failed AA contrast against both white and the light grey section backgrounds. I calculated the darkest tone that passes 4.5:1 on both while remaining recognisably the same brand colour.
A problem worth describing
Partway through, the client switched the site to a different WordPress theme. It broke in eight separate ways at once: a white strip under the header on every page, a green glow on every button, fonts loading from Google again, headings in the wrong colour and typeface, the admin's login name exposed on blog posts, English text on a German site — and, most seriously, the header and footer collapsing into bulleted lists on blog and listing pages.
That last one had a non-obvious cause: Elementor only loads the stylesheets for its own widgets on pages it built. The header is an Elementor template, but a blog post is not an Elementor page — so the header's styling never loaded there. It had been invisible until then only because every page happened to contain the same widget types.
I traced all eight symptoms to the single change, fixed them without editing the theme's own files (so the client can still update it), and documented what to re-check after any future theme change.
What I did
Design, front-end build, custom WordPress plugin development, German copywriting, performance engineering, accessibility, SEO and the GDPR compliance layer — plus the verification process that caught the issues above, which relied on measuring real browser behaviour rather than trusting how things looked.