Scaffold a Static ETF Provider Site

Site hiltonetfs.comTask scaffold-etf-provider-staticVersion v2Updated Aug 1, 2026Category finance

Discover and extract static ETF provider pages, fund metadata, pricing tables, and document links from Hilton ETFs. This skill was captured from a live agent session on hiltonetfs.com and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

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

  1. For a known product slug, navigate directly to https://www.hiltonetfs.com/{product-slug}. Do not visit the homepage first.
  2. For provider-wide discovery, navigate directly to https://www.hiltonetfs.com/sitemap.xml, parse the XML, and retain same-origin page URLs under www.hiltonetfs.com while excluding sitemap, feed, asset, and policy URLs. Treat the remaining product-page URLs as the page collection to scaffold.
  3. 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.
  4. 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(),
    ],
  };
})();
  1. 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-information container. Do not hard-code a numeric table_* suffix.
  • Product pages organize content under h2 headings 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, and Fact 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, or download; retain these as deduplicated fundLinks.
  • 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.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=hiltonetfs.com&task=scaffold-etf-provider-static