PageSourceSearch

https://www.banquemondiale.org/ext/scripts/schema.js

js banquemondiale.org collected 2026-09-24 08:48:44 UTC 7,449 bytes, 221 lines download raw bytes

1import { fetchPlaceholders, getMetadata } from "./aem.js";
2import { getLanguage, PATH_PREFIX } from "./utils.js";
3
4/**
5 * Fetches schema data from API, transforms it into structured data,
6 * and injects it into the document head as a script tag.
7 */
8export async function insertSchema() {
9    let pagePath = window.location.pathname;
10    let schemaApiUrl = "";
11    if (pagePath.startsWith("/content")) {
12        schemaApiUrl = pagePath.replace(".html", ".wbgschema");
13    } else {
14        const globalProperties = await fetchPlaceholders(PATH_PREFIX);
15
16        if (!globalProperties?.schemaUrl) {
17            console.warn(
18                "Schema.js - No schemaUrl found in global properties. Skipping structured data injection."
19            );
20            return;
21        }
22        const environment = globalProperties?.environment
23            ? globalProperties.environment.toLowerCase()
24            : "";
25        schemaApiUrl = `${globalProperties?.schemaUrl}${pagePath}${environment === "qa" || environment === "dev"
26                ? `?env=${environment.toLowerCase()}`
27                : ""
28            }`;
29    }
30
31    fetch(schemaApiUrl)
32        .then((response) => {
33            if (!response.ok) {
34                throw new Error(`HTTP error! status: ${response.status}`);
35            } else {
36                return response.json();
37            }
38        })
39        .then((apiData) => {
40            if (!apiData || typeof apiData !== "object") {
41                console.warn("schema.js - Invalid or empty data received from API");
42                return;
43            }
44
45            // Transform API data to actual schema structure
46            const structuredData = createStructuredData(apiData.data);
47
48            const structuredDataText = JSON.stringify(structuredData, null, 2);
49
50            // Remove any existing schema script for this path to avoid duplicates
51            const existingScript = document.querySelector(
52                'script[type="application/ld+json"]'
53            );
54            if (existingScript) {
55                existingScript.remove();
56            }
57
58            const schemaScript = document.createElement("script");
59            schemaScript.setAttribute("type", "application/ld+json");
60            schemaScript.textContent = structuredDataText;
61            document.head.appendChild(schemaScript);
62        })
63        .catch((error) => {
64            console.error("Error fetching schema data:", error);
65        });
66}
67
68/**
69 * Transforms API response data into structured data format
70 * @param {Object} apiData - Raw data from the API response
71 * @returns {Object} - structured data object
72 */
73function createStructuredData(apiData) {
74    const {
75        title,
76        navTitle,
77        pageTitle,
78        pageName,
79        description,
80        primaryImageOfPage,
81        publisher,
82        organization,
83        breadcrumbs,
84        contacts,
85    } = apiData;
86    const { pathname: pagePath, href: currentPageURL } = window.location;
87
88    const getName = () => {
89        if (title && title.trim()) return title.trim();
90        if (navTitle && navTitle.trim()) return navTitle.trim();
91        if (pageTitle && pageTitle.trim()) return pageTitle.trim();
92        if (pageName && pageName.trim()) return pageName.trim();
93        return "World Bank Group";
94    };
95
96    const getDescription = () => {
97        if (description && description.trim()) return description.trim();
98        if (getMetadata("description")) return getMetadata("description");
99        return "";
100    };
101
102    const getBreadcrumbItems = () => {
103        if (!breadcrumbs || !Array.isArray(breadcrumbs)) {
104            return [];
105        }
106        return breadcrumbs.map((bcrumb) => ({
107            "@type": "ListItem",
108            position: bcrumb.position,
109            name: bcrumb.name,
110            item: bcrumb.item,
111        }));
112    };
113
114    const getType = () => {
115        if (getMetadata("schema-type")) return getMetadata("schema-type");
116        if (pagePath.endsWith("home")) return "WebSite";
117        return "WebPage";
118    };
119    const isRegionPage = pagePath.includes('/region/');
120
121    let structuredData = {
122        "@context": "https://schema.org",
123        "@graph": [],
124    };
125
126    let finalPrimaryImageOfPage = JSON.parse(JSON.stringify(primaryImageOfPage));
127    if (primaryImageOfPage && primaryImageOfPage?.originalPath) {
128        delete finalPrimaryImageOfPage?.originalPath;
129    }
130
131    const pageData = {
132        "@type": getType(),
133        url: currentPageURL,
134        name: getName(),
135        ...(!pagePath?.endsWith("home") && {
136            description: getDescription(),
137        }),
138        ...(getType() !== "Person" && { inLanguage: getLanguage() }),
139        ...(pagePath?.endsWith("home") &&
140            organization?.image && { image: organization.image }),
141        ...(pagePath?.endsWith("home") && {
142            potentialAction: {
143                "@type": "SearchAction",
144                target: "https://www.worldbank.org/en/search?q={search_term_string}",
145                "query-input": "required name=search_term_string",
146            },
147        }),
148        ...(finalPrimaryImageOfPage &&
149            typeof finalPrimaryImageOfPage === "object" &&
150            Object.keys(finalPrimaryImageOfPage).length > 0 &&
151            !pagePath?.endsWith("home") &&
152            getType() !== "Person" && {
153            primaryImageOfPage: finalPrimaryImageOfPage,
154        }),
155        ...(publisher &&
156            typeof publisher === "object" &&
157            Object.keys(publisher).length > 0 &&
158            getType() !== "Person" && {
159            publisher: publisher,
160        }),
161    };
162
163    if (
164        apiData["bio-detail"] &&
165        typeof apiData["bio-detail"] === "object" &&
166        Object.keys(apiData["bio-detail"]).length > 0
167    ) {
168        let sameAs = [];
169        const links = Object.keys(apiData["bio-detail"])?.filter((item) =>
170            item.includes("-link")
171        );
172        links.forEach((link) => {
173            if (apiData["bio-detail"][link]) {
174                sameAs.push(apiData["bio-detail"][link].trim());
175            }
176        });
177        pageData.jobTitle = apiData["bio-detail"]["job-title"]?.trim();
178        pageData.worksFor = apiData.worksfor;
179        pageData.sameAs = sameAs;
180        pageData.image = apiData["bio-detail"].image?.trim();
181    }
182
183    structuredData["@graph"].push(pageData);
184
185    if (
186        organization &&
187        typeof organization === "object" &&
188        Object.keys(organization) &&
189        getType() !== "Person" &&
190        !isRegionPage
191    ) {
192        let finalOrganization = JSON.parse(JSON.stringify(organization));
193        if (pagePath.endsWith("home")) {
194            delete finalOrganization?.image;
195        }
196        structuredData["@graph"].push(finalOrganization);
197    }
198
199    const breadcrumbItems = getBreadcrumbItems();
200
201    if (pagePath.endsWith("contacts")) {
202        const contactsSchema = {
203            ...contacts,
204            ...(breadcrumbItems?.length > 0 && {
205                breadcrumb: {
206                    "@type": "BreadcrumbList",
207                    itemListElement: breadcrumbItems,
208                },
209            }),
210        };
211        structuredData["@graph"].push(contactsSchema);
212    } else {
213        if (breadcrumbItems.length > 0) {
214            structuredData["@graph"].push({
215                "@type": "BreadcrumbList",
216                itemListElement: breadcrumbItems,
217            });
218        }
219    }
220    return structuredData;
221}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.