Purpose
Build a structured static-site representation of Hilton ETFs provider pages, including discoverable page URLs, fund identity, fund-detail tables, investment objectives, descriptive sections, pricing data, and links to fund documents.
When to Use
Use this for a provider-level scaffold or for extracting one or more Hilton ETF product pages. It is suitable when the caller supplies a product slug, or when all publicly listed provider pages should be discovered from the sitemap.
Workflow
- For a known product slug, navigate directly to
https://www.hiltonetfs.com/{product-slug}. Do not visit the homepage first. - For provider-wide discovery, navigate directly to
https://www.hiltonetfs.com/sitemap.xml, parse the XML, and retain same-origin page URLs underwww.hiltonetfs.comwhile excluding sitemap, feed, asset, and policy URLs. Treat the remaining product-page URLs as the page collection to scaffold. - On each product page, wait for
table[id^="table_"],#fund-information, or another applicable fund-data table when present; some fund data is populated after initial DOM content loads. - Run this extractor once on each loaded page:
(() => {
const clean = (value) => (value || "").replace(/\\s+/g, " ").trim();
const text = (node) => clean(node?.innerText || node?.textContent || "");
const h1 = document.querySelector("h1");
const canonical = document.querySelector('link[rel="canonical"]')?.href || null;
const headings = [...document.querySelectorAll("h2")];
const sections = headings.map((heading) => {
const section = heading.closest("section");
if (section)
return { heading: text(heading), id: heading.id || null, text: text(section) };
const parts = [text(heading)];
let node = heading.nextElementSibling;
let count = 0;
while (node && count < 8 && !/^H[1-6]$/.test(node.tagName)) {
const value = text(node);
if (value) parts.push(value);
node = node.nextElementSibling;
count++;
}
return {
heading: text(heading),
id: heading.id || null,
text: clean(parts.join(" ")),
};
});
const tableNodes = [
...document.querySelectorAll('table[id^="table_"], #fund-information'),
];
const tables = [
...new Map(
tableNodes.map((table) => [
table,
{
id: table.id || null,
headers: [...table.querySelectorAll("thead th")].map(text),
rows: [...table.querySelectorAll("tbody tr, tr")]
.map((row) => [...row.querySelectorAll("th, td")].map(text))
.filter((row) => row.length),
},
]),
).values(),
];
const objectiveNode = [...document.querySelectorAll("p, div")].find(
(node) => node.children.length < 3 && /Investment Objective:/i.test(text(node)),
);
const documents = [...document.querySelectorAll("a[href]")]
.map((a) => ({ label: text(a), href: a.href || a.getAttribute("href") }))
.filter((link) =>
/^(Prospectus|Summary Prospectus|SAI|Fact Sheet)$/i.test(link.label),
);
const fundLinks = [...document.querySelectorAll("a[href]")]
.map((a) => ({ label: text(a), href: a.href }))
.filter((link) =>
/prospectus|fact.?sheet|statement|holdings|download|\\.pdf(?:$|\\?)/i.test(
`${link.label} ${link.href}`,
),
);
return {
url: location.href,
canonical,
title: document.title,
h1: text(h1),
h2: headings.map(text),
investmentObjective: objectiveNode ? text(objectiveNode) : null,
sections,
tables,
documents,
fundLinks: [
...new Map(
[...documents, ...fundLinks]
.filter((link) => link.href)
.map((link) => [link.href, link]),
).values(),
],
};
})();- Combine the per-page objects under their source URLs. Preserve table rows as arrays because the site uses dynamically numbered
table_*identifiers and may expose multiple table types.
Site-Specific Gotchas
- The provider sitemap is directly available at
/sitemap.xml; product URLs observed on this host use a no-trailing-slash slug form. - Fund-data tables may use IDs beginning with
table_or the stable#fund-informationcontainer. Do not hard-code a numerictable_*suffix. - Product pages organize content under
h2headings such as fund overview, fund details, and fund data/pricing. The extractor captures the enclosing section where available and otherwise collects following sibling content. - The investment objective may be rendered as a small paragraph or div containing the literal
Investment Objective:label; extract it separately in addition to section text. - Document links are labeled with exact short labels such as
Prospectus,Summary Prospectus,SAI, andFact Sheet; retain their hrefs rather than attempting to infer document URLs. - PDF and other fund-resource links may use labels or URLs containing
prospectus,fact sheet,statement,holdings, ordownload; retain these as deduplicatedfundLinks. - Some related ETF infrastructure was observed on
unlimitedetfs.com, including ticker-style paths and a shared prospectus route. Treat those as external related resources only when explicitly linked from the Hilton page; do not substitute them for Hilton URLs or guess ticker paths. - Cookie/consent handling may be present on related ETF pages. Prefer direct Hilton product URLs and extract the page without relying on homepage navigation.
Expected Output
Return a provider scaffold containing the discovered page URL list and, for each loaded product page, the page URL, canonical/title metadata, H1/H2 headings, investment objective, section text, all applicable fund-information and table_* headers and rows, and deduplicated fund-document and resource links.