Skip to content

Commit 40b079a

Browse files
arteria32Denis Ryabko
andauthored
feat(Map): integrate Schema.org microdata for Map components (#1326)
* feat(Map): integrate Schema.org microdata for GeoCoordinates in GoogleMap and YandexMap components * fix(Map): remove unwanted div from google map * feat(Map): rework schema.org to JSON-LD format * fix(Map): remove any from microdata schema --------- Co-authored-by: Denis Ryabko <[email protected]>
1 parent 01cd127 commit 40b079a

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

src/components/Map/GoogleMap.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@ const GoogleMap = (props: GMapProps) => {
6262
};
6363
}, [forceAspectRatio, isMobile]);
6464

65+
// Generate Schema.org JSON-LD for Google Map
66+
const mapMicrodataScript = React.useMemo(() => {
67+
if (!address) {
68+
return null;
69+
}
70+
71+
const json = JSON.stringify({
72+
'@context': 'https://schema.org',
73+
'@type': 'Place',
74+
address,
75+
});
76+
77+
return <script type="application/ld+json" dangerouslySetInnerHTML={{__html: json}} />;
78+
}, [address]);
79+
6580
if (!apiKey || !address) {
6681
return null;
6782
}
@@ -78,7 +93,9 @@ const GoogleMap = (props: GMapProps) => {
7893
allowFullScreen
7994
referrerPolicy="no-referrer-when-downgrade"
8095
src={src}
81-
/>
96+
>
97+
{mapMicrodataScript}
98+
</iframe>
8299
);
83100
};
84101

src/components/Map/YMap/YandexMap.tsx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import debounce from 'lodash/debounce';
66
import {LocaleContext} from '../../../context/localeContext/localeContext';
77
import {MapsContext} from '../../../context/mapsContext/mapsContext';
88
import {MobileContext} from '../../../context/mobileContext';
9-
import {YMapMarkerLabelPrivate, YMapMarkerPrivate, YMapProps} from '../../../models';
9+
import {YMapMarker, YMapMarkerLabelPrivate, YMapMarkerPrivate, YMapProps} from '../../../models';
1010
import {block} from '../../../utils';
1111
import ErrorWrapper from '../../ErrorWrapper/ErrorWrapper';
1212
import {getMapHeight} from '../helpers';
@@ -28,6 +28,27 @@ const BALLOON_DISABLING_MARKER_OPTIONS: YMapMarkerLabelPrivate = {
2828
interactivityModel: 'default#silent',
2929
};
3030

31+
// Helper function to convert YMapMarker to Schema.org Place object
32+
const markerToSchemaPlace = (marker: YMapMarker) => {
33+
return {
34+
'@type': 'Place',
35+
address: marker.address
36+
? {
37+
'@type': 'Text',
38+
'@value': marker.address,
39+
}
40+
: undefined,
41+
geo:
42+
marker.coordinate && marker.coordinate.length === 2
43+
? {
44+
'@type': 'GeoCoordinates',
45+
latitude: marker.coordinate[0],
46+
longitude: marker.coordinate[1],
47+
}
48+
: undefined,
49+
};
50+
};
51+
3152
const YandexMap = (props: YMapProps) => {
3253
const {
3354
markers,
@@ -140,6 +161,27 @@ const YandexMap = (props: YMapProps) => {
140161
}
141162
}, [ymap, markers, zoom, disableBalloons, areaMargin]);
142163

164+
const mapMicrodataScript = React.useMemo(() => {
165+
if (!markers.length) {
166+
return null;
167+
}
168+
169+
const places = markers
170+
.filter((marker) => marker.address || marker.coordinate)
171+
.map(markerToSchemaPlace);
172+
173+
if (places.length === 0) {
174+
return null;
175+
}
176+
177+
const json = JSON.stringify({
178+
'@context': 'https://schema.org',
179+
'@graph': places,
180+
});
181+
182+
return <script type="application/ld+json" dangerouslySetInnerHTML={{__html: json}} />;
183+
}, [markers]);
184+
143185
if (!markers) return null;
144186

145187
return (
@@ -151,6 +193,7 @@ const YandexMap = (props: YMapProps) => {
151193
className={b('wrapper')}
152194
>
153195
<div className={b('wrapper')}>
196+
{mapMicrodataScript}
154197
{/* hidden - to show the map after calculating the center */}
155198
<div
156199
id={containerId}

0 commit comments

Comments
 (0)