06-reference/research

phenom people spa architecture monitoring

2026-07-12·research-brief·source: deep-research·by ray
phenom-peoplejob-signal-monitoringphdataats-scrapingbusiness-development

Phenom People's SPA Job-Posting Architecture, and How to Monitor It for Hiring Signals Without a Paid Contract

Why this is in the vault

Kwik Trip — a phData enterprise client — runs Phenom People for talent management, and the 2026-07-13 meeting prep flagged a parked "Phenom scraper" ticket because JS-rendered career pages appeared to block standard scraping. This brief resolves that assumption (the SPA is backed by a plain JSON POST endpoint, no headless browser needed) and provides the concrete recipe for building a hiring-signal monitor as a Cloudflare Worker cron against the phData client portfolio — a direct BD signal feed for RDCO's phData engagement.

The question

How does Phenom People's SPA architecture serve enterprise job postings, and what are reliable ways to monitor it for hiring-signal changes without a paid contract? (Context: Kwik Trip and other phData enterprise clients run Phenom for talent management; the 7/13 Kwik Trip prep flags "Phenom scraper is queued" because JS-rendered pages with tenantRefNum params block standard scraping. The point is detecting a client's org/hiring shifts as a BD signal for phData / RDCO.)

What we already know (from the vault)

What the web says

Convergences and contradictions

Synthesis for RDCO

There is a concrete, no-contract monitoring recipe, and it's cheap. For any Phenom tenant, do a one-time capture of the refNum from the career-site HTML (phApp config; Kwik Trip = KTQKTRUS), then poll POST https://{tenant-domain}/widgets with a JSON body {"ddoKey":"refineSearch","refNum":"<code>","pageName":"search-results","from":0,"size":100,"lang":"en_global", ...}, paginating via from/size until you've walked totalHits. The response refineSearch.jobs[] gives you the structured postings (title, location, category, requisition/job id, and — the fields the sitemap-slug method couldn't reach — posting/opening metadata). This is exactly the request the browser SPA already makes, so no headless Chromium, no Playwright, no paid feed — just an HTTP POST and a JSON parse.

Turn that into a hiring-signal monitor by snapshotting each tenant weekly and diffing against the prior snapshot: track (a) totalHits trend, (b) net-new requisition ids, (c) removed/filled reqs, and (d) category/title/location shifts. For phData BD, the load-bearing deltas are role-family movements — e.g., a burst of Kwik Trip data-engineer/BI reqs (currently zero in the sitemap snapshot) would flip the "12-person team not visibly scaling" read into an active-hiring signal worth a partner conversation, and a spike in security/infra reqs corroborates a platform build-out. Run it as a Cloudflare Worker cron (we already have the rails) writing snapshots to R2/D1, one row per tenant per poll, with a simple diff emitting a Notion task or channel ping when a threshold trips.

Two guardrails before productionizing across the client portfolio. First, verify Cloudflare posture per tenant — hit jobs.kwiktrip.com/widgets once with browser-like headers; if it 403s, add a session-cookie warm-up step (navigate the site root first) or fall back to a single Playwright session to mint cookies, then reuse them for cheap POSTs. Second, do a ToS/robots pass: the vault notes phenomtrack.js in Kwik Trip's robots.txt; confirm /widgets isn't disallowed and keep volume conservative (daily-cache cadence, single low-rate poller) so this reads as courteous monitoring, not aggression — this is a client's site, and the BD upside is not worth an IP block or a relationship ding. Net: this is a reversible, low-cost build that unblocks the parked jobs-snapshot ticket and generalizes to every phData client on Phenom by swapping one refNum.

Open follow-ups

Related

Sources