Retrieve the rendered 7shifts time-clock punch audit for {date}, preserving punch rows, visible table structure, page metadata, and authentication or session-expiry indicators in a structured result.
Use Cases
Use for nightly or historical audits of employee clock-in, clock-out, and punch-adjustment records in 7shifts. The caller must have an authenticated 7shifts session and should provide the requested business date in MM/DD/YYYY form. Use the separate login-to-7shifts skill when authentication is required. This workflow also distinguishes a genuine expired session from a page that is merely waiting on Cloudflare clearance.
Automation Flow
- In one browser automation batch, navigate directly to
https://app.7shifts.com/time_clocking_addonwith a load timeout of about 40 seconds. - Allow the initial page/client shell to settle for about 8 seconds. If a Cloudflare challenge is present, invoke the browser's Cloudflare solver with a timeout of about 30 seconds, then wait another 8–10 seconds for the application to resume. Do not navigate to or retain transient Cloudflare challenge URLs.
- Run the following
evaluate()on the loaded page. It extracts visible HTML tables when present, falls back to visible ARIA rows, captures date controls and audit metadata, and returns a bounded text fallback.
(() => {
const clean = value => String(value || '').replace(/\u00a0/g, ' ').replace(/\s+/g, ' ').trim();
const textOf = el => clean(el?.innerText || el?.textContent || '');
const visible = el => !!el && el.offsetParent !== null;
const visibleTables = [...document.querySelectorAll('table')].filter(visible);
const tables = visibleTables.map((table, index) => ({
index,
caption: textOf(table.querySelector('caption')),
headers: [...table.querySelectorAll('thead th')].map(textOf).filter(Boolean),
rows: [...table.querySelectorAll('tbody tr, tr')]
.map(row => [...row.querySelectorAll(':scope > th, :scope > td')].map(textOf))
.filter(row => row.some(Boolean))
})).filter(table => table.rows.length);
const ariaRows = tables.length ? [] : [...document.querySelectorAll('[role="row"]')]
.filter(visible)
.map(row => [...row.querySelectorAll(':scope > [role="cell"], :scope > [role="gridcell"], :scope > [role="columnheader"]')].map(textOf))
.filter(row => row.some(Boolean));
const controls = [...document.querySelectorAll('input, select, button')]
.filter(visible)
.map(el => ({
tag: el.tagName.toLowerCase(),
type: el.getAttribute('type') || '',
name: el.getAttribute('name') || '',
ariaLabel: el.getAttribute('aria-label') || '',
placeholder: el.getAttribute('placeholder') || '',
value: 'value' in el ? clean(el.value) : textOf(el)
}))
.filter(control => control.value || control.name || control.ariaLabel || control.placeholder);
const bodyText = textOf(document.body);
const displayedDate = bodyText.match(/(?:business date|audit date|date|for)\s*[:\-]?\s*([A-Za-z]{3,9}\s+\d{1,2},\s+\d{4}|\d{1,2}\/\d{1,2}\/\d{4}|\d{4}-\d{2}-\d{2})/i)?.[1] || '';
const error = bodyText.match(/sign in|log in|unauthorized|forbidden|error|unable to load|no data|session expired/i)?.[0] || '';
return {
url: location.href,
title: document.title,
path: location.pathname,
reportType: '7shifts time-clock punches',
displayedDate,
tableCount: tables.length,
tables,
ariaRows,
controls,
visibleText: bodyText.slice(0, 20000),
authOrError: error
};
})()- Verify that the displayed audit date, when present, matches
{date}. This route was observed without a stable date query parameter; do not fabricate or append date parameters. If the page is showing another date, use the page's own authenticated date control before rerunning the evaluator, and treat an unverified date as an incomplete audit. - Interpret the result only after Cloudflare processing: a login redirect, password form, sign-in/session-expired text, or unauthorized response indicates that the session is expired or otherwise unauthenticated; a Cloudflare challenge without those indicators is not proof of expiry. An authenticated application shell with rendered report content indicates the session remains usable.
Possible Friction Points
- The stable feature route observed for this audit is
/time_clocking_addon, rather than a homepage navigation sequence. - 7shifts renders the time-clock content client-side; wait after navigation and Cloudflare resolution before extracting rows.
- The reliable challenge sequence observed on this route is an initial wait of roughly 8 seconds, Cloudflare solving when needed, and a further 8–10 second render wait.
- The route can present a Cloudflare challenge before the application becomes available. Use the browser Cloudflare solver and then wait for the app to render; do not reuse challenge URLs or challenge parameters.
- No stable date query parameter was observed for this route. Never guess a date parameter or rely on the URL alone; verify the date displayed by the page or its date control.
- Punch data may be rendered as ordinary HTML tables or ARIA grid rows. The evaluator handles both and preserves row cell boundaries.
- If the page redirects to authentication, invoke
login-to-7shiftsand retry the direct route. Do not retain transient OAuth URLs or expose credentials. - A login/session-expiry indicator after Cloudflare clearance is meaningful; a challenge or sparse page before clearance is only a loading/anti-bot state.
- An empty result, an authentication message, a displayed date different from
{date}, or a page still showing a Cloudflare challenge is not a successful historical audit.