From 1f54bcfd3f522fe7d3e25f1db7d3359a37b4898a Mon Sep 17 00:00:00 2001 From: "Leon C." <44192468+leonbeon@users.noreply.github.com> Date: Tue, 20 May 2025 12:44:43 +0200 Subject: [PATCH] ImmoScout: Allow web paths with SEO optimization to be filtered to query params (#128) --- .../immoscout/immoscout-web-translater.js | 41 +++++++++++++++++-- .../immoscout-web-translater.test.js | 10 +++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lib/services/immoscout/immoscout-web-translater.js b/lib/services/immoscout/immoscout-web-translater.js index a7b61a7..78fcd07 100644 --- a/lib/services/immoscout/immoscout-web-translater.js +++ b/lib/services/immoscout/immoscout-web-translater.js @@ -79,6 +79,7 @@ const PARAM_NAME_MAP = { geocoordinates: 'geocoordinates', shape: 'shape', sorting: 'sorting', + newbuilding: 'newbuilding' }; const EQUIPMENT_MAP = { @@ -89,6 +90,7 @@ const EQUIPMENT_MAP = { garden: 'garden', guesttoilet: 'guestToilet', balcony: 'balcony', + handicappedaccessible: 'handicappedAccessible' }; const REAL_ESTATE_TYPE = { @@ -98,6 +100,29 @@ const REAL_ESTATE_TYPE = { 'haus-kaufen': 'housebuy', }; +const WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP = { + // Category "Balkon/Terrasse" + 'wohnung-mit-balkon-mieten': { equipment: ['balcony'] }, + 'wohnung-mit-garten-mieten': { equipment: ['garden'] }, + // Category "Wohnungstyp" + 'souterrainwohnung-mieten': { apartmenttypes: ['halfbasement'] }, + 'erdgeschosswohnung-mieten': { apartmenttypes: ['groundfloor'] }, + 'hochparterrewohnung-mieten': { apartmenttypes: ['raisedgroundfloor'] }, + 'etagenwohnung-mieten': { apartmenttypes: ['apartment'] }, + 'loft-mieten': { apartmenttypes: ['loft'] }, + 'maisonette-mieten': { apartmenttypes: ['maisonette'] }, + 'terrassenwohnung-mieten': { apartmenttypes: ['terracedflat'] }, + 'penthouse-mieten': { apartmenttypes: ['penthouse'] }, + 'dachgeschosswohnung-mieten': { apartmenttypes: ['roofstorey'] }, + // Category "Ausstattung" + 'wohnung-mit-garage-mieten': { equipment: ['parking'] }, + 'wohnung-mit-einbaukueche-mieten': { equipment: ['builtinkitchen'] }, + 'wohnung-mit-keller-mieten': { equipment: ['cellar'] }, + // Category "Merkmale" + 'neubauwohnung-mieten': { newbuilding: true }, + 'barrierefreie-wohnung-mieten': { equipment: ['handicappedaccessible'] } +}; + export function convertWebToMobile(webUrl) { let url; try { @@ -112,9 +137,17 @@ export function convertWebToMobile(webUrl) { } const realTypeKey = segments.at(-1); - const realType = REAL_ESTATE_TYPE[realTypeKey]; + let realType = REAL_ESTATE_TYPE[realTypeKey]; + let additionalParamsFromWebPath; + if (!realType) { - throw new Error(`Real estate type not found: ${realTypeKey}`); + // Test for seo optimized apartment path (only used on the ImmoScout web app) + if (WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey]) { + additionalParamsFromWebPath = WEB_PATH_TO_APARTMENT_EQUIPMENT_MAP[realTypeKey]; + realType = REAL_ESTATE_TYPE['wohnung-mieten']; + } else { + throw new Error(`Real estate type not found: ${realTypeKey}`); + } } if (segments.includes('shape')) { @@ -132,6 +165,7 @@ export function convertWebToMobile(webUrl) { searchType: isRadius ? 'radius' : 'region', realestatetype: realType, ...(isRadius ? {} : { geocodes }), + ...additionalParamsFromWebPath }; if (webParams.geocoordinates) { @@ -141,7 +175,8 @@ export function convertWebToMobile(webUrl) { for (const [key, val] of Object.entries(webParams)) { if (key === 'equipment') { const items = [].concat(val).flatMap((v) => `${v}`.split(',')); - mobileParams[PARAM_NAME_MAP[key]] = items.map((item) => EQUIPMENT_MAP[item.toLowerCase()]).filter(Boolean); + const currentEquipmentParams = mobileParams[PARAM_NAME_MAP[key]]; + mobileParams[PARAM_NAME_MAP[key]] = [...currentEquipmentParams ?? [], ...items.map((item) => EQUIPMENT_MAP[item.toLowerCase()]).filter(Boolean)]; } else { mobileParams[PARAM_NAME_MAP[key]] = val; } diff --git a/test/services/immoscout/immoscout-web-translater.test.js b/test/services/immoscout/immoscout-web-translater.test.js index ef95272..365eb87 100644 --- a/test/services/immoscout/immoscout-web-translater.test.js +++ b/test/services/immoscout/immoscout-web-translater.test.js @@ -16,6 +16,16 @@ describe('#immoscout-mobile URL conversion', () => { expect(actualMobileUrl).to.equal(expectedMobileUrl); }); + // Test URL conversion of web-only SEO path + it('should convert a SEO web path to the correct query params', () => { + const webUrl = + 'https://www.immobilienscout24.de/Suche/de/berlin/berlin/wohnung-mit-balkon-mieten?equipment=garden'; + + const converted = convertWebToMobile(webUrl); + const queryParams = new URL(converted).searchParams; + expect(queryParams.get('equipment').split(',')).to.include.members(['garden', 'balcony']); + }); + // Test URL conversion with unsupported query parameters it('should remove unsupported query parameters', () => { const webUrl = 'https://www.immobilienscout24.de/Suche/de/berlin/berlin/wohnung-mieten?minimuminternetspeed=100000';