Report & Query Guide (Redash / SQL Reference)
A reference of Redash queries and SQL scripts for zone hours, portfolio, and subcontractor reports
Table of Contents:
Zone Hours (Replacement for Zone Detection)
Instead of displaying a row for every detection, this report calculates the total time spent in a zone until the worker is detected in a different zone. This approach significantly reduces the number of rows. In the previous Zone Detection report, a worker could have `dozens or even hundreds` of entries if they remained in the same zone throughout the day (e.g., 9:00, 9:06, 9:12, 9:18, etc.). With the new `Zone Hours` report, only a `single entry` is recorded for continuous time in a zone. For example: Previous format: - Zone_Name, 9:00 - Zone_Name, 9:06 - Zone_Name, 9:12 - Zone_Name, 9:18 New format: - Zone_Name, 9:00 – 9:18 This update makes the report `more concise and easier` to analyze while preserving the accuracy of time spent in each zone. This report utilizes Campus `RECURSIVE CTEs`, which include the parent site along with all child sites. If you need to run the report for a `single site without its child sites`, you will need to modify the `RECURSIVE CTEs` accordingly. (Templates for these modifications will be added later.)
Updated Jan 2025 Zone Report - Company Totals (Date Range)
Updated Jan 2025 Zone Report - Company Totals (One Date)
Updated March 2025 Zone Report - Worker Hours (Date Range)
Dave’s Notes: There are now two separate reports: 1. Total Hours in Zone This report shows the total amount of time a person spent in each zone over the course of a day. For example, if someone moves from Zone A to Zone B and then back to Zone A, the report will add up all the time spent in Zone A during the day. 2. Zone Movements This report lists each individual movement between zones. You’ll see entries showing someone moving from Zone A to Zone B and then back to Zone A, along with the amount of time spent in each zone between movements. Issue Fixed: Sessions Longer Than 24 Hours Previously, there was a bug with stationary badges that caused total hours to exceed 24 in a day. For example, a session might appear as starting at 7:14 AM on 3/14 and ending at 8:20 AM — but it was actually spanning from 7:14 AM on 3/14 to 8:20 AM on 3/15. This led to an inflated total for 3/14. Now, these cross-day sessions are automatically split at midnight. The session would end at 11:59 PM on 3/14 and a new session would begin at 12:00 AM on 3/15, preventing overcounting on a single day.
- [https://redash.sitemetric.com/queries/5851/source?p_company_id=["All"]&p_date_range=d_last_7_days&p_hours_between_sessions=6&p_site_id=VA63854302&p_zone=["All"]](https://redash.sitemetric.com/queries/5851/source?p_company_id=%5B%22All%22%5D&p_date_range=d_last_7_days&p_hours_between_sessions=6&p_site_id=VA63854302&p_zone=%5B%22All%22%5D)
- [https://redash.sitemetric.com/queries/5852/source?p_company_id=["All"]&p_date_range=d_last_7_days&p_hours_between_sessions=6&p_site_id=VA63854302&p_zone=["All"]](https://redash.sitemetric.com/queries/5852/source?p_company_id=%5B%22All%22%5D&p_date_range=d_last_7_days&p_hours_between_sessions=6&p_site_id=VA63854302&p_zone=%5B%22All%22%5D)
Updated Jan 2025 Zone Report - Worker Hours (One Date)
Portfolio Reports
Will explain later
Owners Portfolio Project Summary - CompanyUses Owner company_id
Owners Portfolio Project Summary-Cumulative Daily Headcount Chart
Owners Portfolio Project Summary-Sites Daily Headcount Chart
Dashboard Examples
- https://redash.sitemetric.com/dashboards/14482-active-site---daily-headcount?p_company_id=B9E2E12C67
- https://redash.sitemetric.com/dashboards/14487-project-summary
Max Trade Headcount (Weekly & Monthly) In-App Dashboard
Max Trade Headcount (Weekly & Monthly) In-App Dashboard
Max Trades - Monthly Headcount Report Emailed Report
Max Trades - Weekly Headcount Report Emailed Report
Monthly Headcount
[https://redash.sitemetric.com/dashboards/21822-amazon-aws-sites---monthly-headcount?p_project=["All"]](https://redash.sitemetric.com/dashboards/21822-amazon-aws-sites---monthly-headcount?p_project=%5B%22All%22%5D)
Report Naming Convention
Standardized format for naming reports
Dashboards
- Daily Report — CONFIRMED NAME: ✅
- Headcount and Hours — ALTERNATIVE IDEAS: Headcount and Hours (Site-Wide)
- Project Summary — CONFIRMED NAME: ✅
- Site Access List — CONFIRMED NAME: ✅
- Real-Time Location Report
- Zone Headcount and Hours — ALTERNATIVE IDEAS: Headcount and Hours (Zone-Specific)
- Zone Detection — ALTERNATIVE IDEAS: Zone Trace, Zone Movements, Worker Location Trace, Worker Zone Trace, Worker Zone Movements,
- Zone Summary — ALTERNATIVE IDEAS: Zone Summary (Hourly), Zone Summary (By Hour)
Queries
Daily Worker Hours - List of individual worker's daily hours
- Daily Worker Hours — DESCRIPTION: List of individual worker's daily hours; CONFIRMED NAME: ✅
Equipment and Zone Counts
Used as a case study for a marketing paper.
Count of Zone and Equipment at a site - Count at Campus(Parent + Child)
Monthly Chart - Monthly Deployment numbers
Active Sites with Address and Zip
https://redash.sitemetric.com/queries/5731/source
Subcontractor Daily Report
This version of the report has 3 tabs: 1. Daily Company Totals – Displays the daily headcount and total hours for each company, along with a count of badges left onsite overnight. *Overnight badges are excluded from the headcount and total hours.* 2. Daily Worker Hours – Lists the total hours worked by each worker. *Stationary workers are not included.* 3. Stationary/Overnight Badges – Provides a list of all badges that remained onsite overnight. `The queries do not include the site settings or tiered subs`
Daily Company Totals
- [https://redash.sitemetric.com/queries/5738/source?p_Date=d_yesterday&p_company_id=["8XE6AN0VZ0"]&p_dates_to_exclude=["2024-12-25"]&p_day_numbers=["0"%2C"1"%2C"2"%2C"3"%2C"4"%2C"5"%2C"6"]&p_site_id=GA77596503&p_sitemetric_id=["All"]](https://redash.sitemetric.com/queries/5738/source?p_Date=d_yesterday&p_company_id=%5B%228XE6AN0VZ0%22%5D&p_dates_to_exclude=%5B%222024-12-25%22%5D&p_day_numbers=%5B%220%22%2C%221%22%2C%222%22%2C%223%22%2C%224%22%2C%225%22%2C%226%22%5D&p_site_id=GA77596503&p_sitemetric_id=%5B%22All%22%5D)
Daily Worker Hours
- [https://redash.sitemetric.com/queries/5739/source?p_Date=d_yesterday&p_company_id=["8XE6AN0VZ0"]&p_dates_to_exclude=["2024-12-25"]&p_day_numbers=["0"%2C"1"%2C"2"%2C"3"%2C"4"%2C"5"%2C"6"]&p_site_id=GA77596503&p_sitemetric_id=["All"]](https://redash.sitemetric.com/queries/5739/source?p_Date=d_yesterday&p_company_id=%5B%228XE6AN0VZ0%22%5D&p_dates_to_exclude=%5B%222024-12-25%22%5D&p_day_numbers=%5B%220%22%2C%221%22%2C%222%22%2C%223%22%2C%224%22%2C%225%22%2C%226%22%5D&p_site_id=GA77596503&p_sitemetric_id=%5B%22All%22%5D)
Stationary/Overnight Badges
- [https://redash.sitemetric.com/queries/5740/source?p_Date=d_yesterday&p_company_id=["8XE6AN0VZ0"]&p_dates_to_exclude=["2024-12-25"]&p_day_numbers=["0"%2C"1"%2C"2"%2C"3"%2C"4"%2C"5"%2C"6"]&p_site_id=GA77596503&p_sitemetric_id=["All"]](https://redash.sitemetric.com/queries/5740/source?p_Date=d_yesterday&p_company_id=%5B%228XE6AN0VZ0%22%5D&p_dates_to_exclude=%5B%222024-12-25%22%5D&p_day_numbers=%5B%220%22%2C%221%22%2C%222%22%2C%223%22%2C%224%22%2C%225%22%2C%226%22%5D&p_site_id=GA77596503&p_sitemetric_id=%5B%22All%22%5D)
Cloning Dashboards
Clone
INSERT INTO and UPDATE site_companies
### INSERT new
company_id(s) INTO thesite_companiestable - This script inserts a predefined list of company_id(s) into thesite_companiestable for a givensite_id. - If a site requires a dropdown of companies for its registration form but has no workers registered yet, some companies might not exist insite_companies. This script ensures those companies are added and skips companies that already exist. - Step 1: 1. Creates a temporary dataset (co) with newcompany_ids. 2. Filters out companies that already exist insite_companies. 3. Inserts only the newcompany_ids. - This prevents duplicate entries and ensures necessary companies are available for site registration. - Step 2: Will add this later - Step 3: Will add this later
Given a site_id and a list of company_id(s), you can run this script:
site_id = AZ4PNYHGGT
company_id = 28CC66592D, 0SFS41FZ7X, 704CEAC675, 2320011E80
-- EXAMPLE:
/*
====================
1. This will INSERT companies that are not already in site_companies
====================
*/
INSERT INTO site_companies (site_id, company_id, parent_id, primary_id, created_at, updated_at, deleted_at)
SELECT * FROM (
SELECT 'TX36633349' AS site_id, '15C2W18TY2' AS company_id, 'XM0YDVUBW4' AS parent_id, 'XM0YDVUBW4' AS primary_id, NOW() AS created_at, NOW() AS updated_at, NULL AS deleted_at UNION ALL
SELECT 'TX36633349', '5879271F9D', '9V4UEDEKCV', '9V4UEDEKCV', NOW(), NOW(), NULL UNION ALL
SELECT 'TX36633349', 'JKYN26D452', '9V4UEDEKCV', '9V4UEDEKCV', NOW(), NOW(), NULL UNION ALL
SELECT 'TX36633349', '848E26231B', '9V4UEDEKCV', '9V4UEDEKCV', NOW(), NOW(), NULL UNION ALL
) co
WHERE NOT EXISTS (
SELECT 1 FROM site_companies sc
WHERE sc.site_id = co.site_id
AND sc.company_id = co.company_id
AND sc.deleted_at IS NULL
);
-- Alternatively, you can do this:
INSERT INTO site_companies (site_id, company_id, parent_id, primary_id, created_at, updated_at, deleted_at)
SELECT co.site_id, co.company_id, co.parent_id, co.primary_id, co.created_at, co.updated_at, co.deleted_at
FROM (
SELECT 'AZ4PNYHGGT' AS site_id, '28CC66592D' AS company_id, '28CC66592D' AS parent_id, '28CC66592D' AS primary_id, NOW() AS created_at, NOW() AS updated_at, NULL AS deleted_at UNION ALL
SELECT 'AZ4PNYHGGT', '0SFS41FZ7X', '0SFS41FZ7X', '0SFS41FZ7X', NOW(), NOW(), NULL UNION ALL
SELECT 'AZ4PNYHGGT', '704CEAC675', '704CEAC675', '704CEAC675', NOW(), NOW(), NULL UNION ALL
SELECT 'AZ4PNYHGGT', '2320011E80', '2320011E80', '2320011E80', NOW(), NOW(), NULL
) co
WHERE NOT EXISTS (
SELECT 1 FROM site_companies sc
WHERE sc.site_id = co.site_id
AND sc.company_id = co.company_id
AND sc.deleted_at IS NULL
);
/*
====================
2. OPTIONAL: Use this if you want to check to see which companies were skipped
because they were already in site_companies, but did not have different
parent companies.
- You can copy the SELECT lines from step 1 — be sure to remove
the NOW(), NOW(), NULL
====================
*/
SELECT sc.site_id, sc.company_id, sc.parent_id, sc.primary_id
FROM site_companies sc
WHERE EXISTS (
SELECT 1 FROM (
SELECT 'TX36633349' AS site_id, '15C2W18TY2' AS company_id, 'XM0YDVUBW4' AS parent_id, 'XM0YDVUBW4' AS primary_id UNION ALL
SELECT 'TX36633349', '5879271F9D', '9V4UEDEKCV', '9V4UEDEKCV' UNION ALL
SELECT 'TX36633349', 'JKYN26D452', '9V4UEDEKCV', '9V4UEDEKCV' UNION ALL
SELECT 'TX36633349', 'PUWPDNTQVW', 'Z6RVQP0SDF', 'Z6RVQP0SDF'
) excluded
WHERE excluded.site_id = sc.site_id
AND excluded.company_id = sc.company_id
AND (excluded.parent_id <> sc.parent_id
OR excluded.primary_id <> sc.primary_id)
);
-- Or to see if a company_id is already in site_companies as a first Tier sub
SELECT site_id, company_id, parent_id, primary_id
FROM site_companies sc
WHERE company_id IN (
'aaaaa',
'aaaaa',
'aaaaa',
'aaaaa'
)
AND site_id = 'ADD_SITE_ID'
AND company_id <> primary_id;
/*
====================
3. Use this to UPDATE multiple companies that are already in site_companies
but do not have different parent_id or primary_id
- You can copy the SELECT lines from STEP 1
Be sure to change NOW(), NOW(), NULL
to NOW() since you are only updating updated_at.
====================
*/
UPDATE site_companies sc
JOIN (
SELECT 'TX36633349' AS site_id, 'A84EBA03E6' AS company_id, '9V4UEDEKCV' AS parent_id, '9V4UEDEKCV' AS primary_id, NOW() AS updated_at UNION ALL
SELECT 'TX36633349', 'VT1G3Q0HCZ', '9V4UEDEKCV', '9V4UEDEKCV', NOW() UNION ALL
SELECT 'TX36633349', 'AC4C6297A8', '9V4UEDEKCV', '9V4UEDEKCV', NOW() UNION ALL
SELECT 'TX36633349', 'AE1CB3005A', 'D7CF129FBF', 'D7CF129FBF', NOW()
) updates
ON sc.site_id = updates.site_id
AND sc.company_id = updates.company_id
AND sc.primary_id = updates.company_id
SET
sc.parent_id = updates.parent_id,
sc.primary_id = updates.primary_id,
sc.updated_at = updates.updated_at;
/*
========================
3.1 Or use this to UPDATE only one company that is already
in site_companies but does not have different parent_id or primary_id
========================
*/
UPDATE site_companies sc
JOIN (
SELECT 'TX36633349' AS site_id, '848E26231B' AS company_id, '9V4UEDEKCV' AS parent_id, '9V4UEDEKCV' AS primary_id, NOW() AS updated_at
) updates
ON sc.site_id = updates.site_id
AND sc.company_id = updates.company_id
SET
sc.parent_id = updates.parent_id,
sc.primary_id = updates.primary_id,
sc.updated_at = updates.updated_at;
Daily Report Dashboard
This is the link to the new, updated Campus Daily Report — let me know if you see any issues with it. You should be able to run with it if you want, but don’t modify this one. - Campus-enabled (if you don’t want that, you can just force it to return a single site) - Date exclusions - Day of week exclusions - Company exclusions - Allowed resource types (defaulting to LABOR only) - Company hierarchies (
site_companies) - Site Settings (ie. hours before stationary, whether to adjust stationary hours, whether to exclude stationary hours, etc.)
https://redash.sitemetric.com/dashboards/15760-campus-daily-report?p_date=d_yesterday
Badges that have not been onsite in X number of days
Not a common report. -
worker_badgestable determines where the badge is billed to
[https://redash.sitemetric.com/queries/5756/source?p_SITE ID=["OH90537338"%2C"OH18359303"]&p_date=d_now&p_days=60](https://redash.sitemetric.com/queries/5756/source?p_SITE%20ID=%5B%22OH90537338%22%2C%22OH18359303%22%5D&p_date=d_now&p_days=60)
Morning Scan Report
List of times each worker scanned today Made into a “Generic Report”
https://redash.sitemetric.com/queries/5798/source?p_Date=d_now&p_site_id=GA27364899#10244
Badge-In Report
Lists the first scan time for each worker onsite.
https://redash.sitemetric.com/queries/5803/source?p_Date=d_now&p_site_id=WAGHU7FAV5
Certification Report
All certs and expiring certs.
form_idis usually from the self-reg form Need to check why the attachments are not working
Report Exclusions
List of all the report exclusions added to a site
https://redash.sitemetric.com/dashboards/16438-report-exclusions?p_site_id=GA6NAA84NK
Max Company Headcounts for the week
List the max daily headcount for each company for the week Tie breaker is the day with the higher hours
[https://redash.sitemetric.com/queries/5813/source?p_Date=d_yesterday&p_company_id=["All"]&p_date_range=d_last_week&p_dates_to_exclude=["2024-12-25"]&p_day_numbers=["0"%2C"1"%2C"2"%2C"3"%2C"4"%2C"5"%2C"6"]&p_site_id=AZ38711074&p_sitemetric_id=["All"]](https://redash.sitemetric.com/queries/5813/source?p_Date=d_yesterday&p_company_id=%5B%22All%22%5D&p_date_range=d_last_week&p_dates_to_exclude=%5B%222024-12-25%22%5D&p_day_numbers=%5B%220%22%2C%221%22%2C%222%22%2C%223%22%2C%224%22%2C%225%22%2C%226%22%5D&p_site_id=AZ38711074&p_sitemetric_id=%5B%22All%22%5D)
Form Dropdown (Hardcoded companies)
List the max daily headcount for each compa
SELECT
name AS text,
name AS value
FROM
companies co
WHERE
co.company_id IN (
'0782FEDC3B',
'U1CFVM85PJ',
'F7D2D029DE',
'5879271F9D'
)
ORDER BY
name
Send this to Nate or whoever put in the request:
CUSTOMER PROJECT SITE_ID https://us.sitemetric.com/api/v3/redash/query/QUERY_ID_GOES_HERE/rows?api_key=API_KEY_GOES_HERE
Report “Inclusions”
When a customer provides a list of companies they want included in their reports only: 1. Interpret the list as an inclusion list, they only want to see data from these specific companies. 2. To implement this, identify all company IDs *with site access* that are not on the inclusion list. 3. Add those company IDs to the Report Exclusions – essentially, you're taking the reverse of the provided list. 4. Use the script below to generate the list of companies to exclude.
SELECT sc.company_id
FROM site_companies sc
WHERE sc.site_id = 'ADD_SITE_ID'
AND sc.company_id NOT IN ('ADD_COMPANY_ID','ADD_COMPANY_ID','ADD_COMPANY_ID','ADD_COMPANY_ID')
AND sc.company_id NOT IN (
SELECT company_id
FROM site_companies
WHERE site_id = 'ADD_SITE_ID'
AND (parent_id IN ('ADD_COMPANY_ID','ADD_COMPANY_ID','ADD_COMPANY_ID','ADD_COMPANY_ID')
OR primary_id IN ('ADD_COMPANY_ID','ADD_COMPANY_ID','ADD_COMPANY_ID','ADD_COMPANY_ID'))
)
If given an excel file with company_id, you can use this
def format_for_sql(input_text):
ids = [line.strip() for line in input_text.strip().splitlines() if line.strip()]
return ', '.join(f"'{id}'" for id in ids) # Wrap each id in single quotes and join with commas and space
# Example company_ids: paste your all your ids here
raw_list = """
66B4293B2B
KPDKHK022W
90337267DC
1H776XTZ4D
7CB48110F6
5E47D054EE
"""
formatted_list = format_for_sql(raw_list)
print(formatted_list)
Insert one Report Exclusion
INSERT INTO site_report_exclusions (site_id, rule_type, created_at, updated_at, deleted_at, value)
SELECT 'GA77596503', 'company_id', NOW(), NOW(), NULL, val
FROM (
SELECT 'E1E8BDC8F7' AS val
) AS exclusions
WHERE NOT EXISTS (
SELECT 1
FROM site_report_exclusions sre
WHERE sre.site_id = 'GA77596503'
AND sre.value = exclusions.val
);
Fixing a worker’s company
For example, if the worker was put into the system under the wrong company for a site, and we need to fix it for the future and historically. First, someone would remove his access and re-grant access with the correct company in the app. Then, as an example:
UPDATE data.dailytech
SET
company_id = 'C72291C959'
WHERE
sitemetric_id = 'NXBP0TNMSS'
AND site_id = 'WA35950425'
AND company_id = '4WTZ7YSQYC';
UPDATE data.dailyhours
SET
company_id = 'C72291C959'
WHERE
sitemetric_id = 'NXBP0TNMSS'
AND site_id = 'WA35950425'
AND company_id = '4WTZ7YSQYC';
UPDATE data.sessions
SET
company_id = 'C72291C959'
WHERE
sitemetric_id = 'NXBP0TNMSS'
AND site_id = 'WA35950425'
AND company_id = '4WTZ7YSQYC';
Sitemetric Worker Report
To run a report on a sitemetric worker on all sites.
[https://redash.sitemetric.com/dashboards/17197-sitemetric-worker-report?p_date_range=2025-03-16--2025-03-22&p_sitemetric_id=["AFZ8149N3B"%2C"AC9EJKIC0J"%2C"17QH7618XG"%2C"2JH64U0YIG"]&p_w73316_date_range=2025-03-16--2025-03-22&p_w73316_sitemetric_id=["AFZ8149N3B"%2C"AC9EJKIC0J"%2C"17QH7618XG"%2C"2JH64U0YIG"]&p_w73317_date_range=2025-03-16--2025-03-22&p_w73317_sitemetric_id=["AFZ8149N3B"%2C"AC9EJKIC0J"%2C"17QH7618XG"%2C"2JH64U0YIG"]](https://redash.sitemetric.com/dashboards/17197-sitemetric-worker-report?p_date_range=2025-03-16--2025-03-22&p_sitemetric_id=%5B%22AFZ8149N3B%22%2C%22AC9EJKIC0J%22%2C%2217QH7618XG%22%2C%222JH64U0YIG%22%5D&p_w73316_date_range=2025-03-16--2025-03-22&p_w73316_sitemetric_id=%5B%22AFZ8149N3B%22%2C%22AC9EJKIC0J%22%2C%2217QH7618XG%22%2C%222JH64U0YIG%22%5D&p_w73317_date_range=2025-03-16--2025-03-22&p_w73317_sitemetric_id=%5B%22AFZ8149N3B%22%2C%22AC9EJKIC0J%22%2C%2217QH7618XG%22%2C%222JH64U0YIG%22%5D)
On-demand: https://us.sitemetric.com/sites/US81228450/reports/on-demand-reports/new/redash-dashboard/17197
Headcount and Hours Report (Worker Hours) (Excel Version)
`Worker Daily Hours`: https://redash.sitemetric.com/queries/5892/source?p_date_range=2025-03-26--2025-03-27&p_site_id=TXP4D6KZV5
`Companies Totals`: https://redash.sitemetric.com/queries/5894/source?p_date_range=d_last_month&p_site_id=TXP4D6KZV5
`Companies Daily`: https://redash.sitemetric.com/queries/5895/source?p_date_range=d_last_month&p_site_id=TXP4D6KZV5
Tiered Subs using Daily Hours (Date)
`Worker Daily Hours`: https://redash.sitemetric.com/queries/5924?p_date=d_now&p_site_id=PAAMV78AG8
`Companies Totals`: https://redash.sitemetric.com/queries/5923?p_date=d_now&p_site_id=PAAMV78AG8
Overnight shifts per Calendar day
(Sub-Tier Company)(Date)
Overnight shifts are split and counted based on the calendar day. For example, on 4/1, if a worker is onsite from 12:00 AM–2:00 AM and again from 10:00 PM–11:59 PM, the Worker Hours tab will show two separate rows — one for 12–2 AM and another for 10–11:59 PM. In the Company Totals tab, the Headcount column counts each worker only once per day, even if they appear on multiple shifts that day.
April 2025
`Company Totals`: https://redash.sitemetric.com/queries/5928/source?p_date=d_now&p_site_id=VA21712216 `Worker Hours`: https://redash.sitemetric.com/queries/5927/source?p_date=d_now&p_site_id=VA21712216
May 13, 2025
`Company Totals`: https://redash.sitemetric.com/queries/6153/source?p_date=d_yesterday&p_site_id=DC87587423 `Worker Hours`: https://redash.sitemetric.com/queries/6149/source?p_date=d_yesterday&p_site_id=DC87587423
`Stationary`: https://redash.sitemetric.com/queries/6152/source?p_date=d_yesterday&p_site_id=DC87587423 `All Detection`: https://redash.sitemetric.com/queries/6150/source?p_date=d_yesterday&p_site_id=DC87587423
May 21, 2025
This version excludes any workers whose first detection was on the day of the emailed report, but includes overnight workers who started the previous day.
`Worker Hours`: https://redash.sitemetric.com/queries/6193/source?p_date=d_yesterday&p_site_id=DC87587423
June 18, 2025
`Worker Hours with Date Range`: [https://redash.sitemetric.com/queries/6332/source?p_company_id=["14F802741E"]&p_date=d_yesterday&p_date_range=2025-06-02--2025-06-16&p_gap_hours=540&p_site_id=GA6NAA84NK](https://redash.sitemetric.com/queries/6332/source?p_company_id=%5B%2214F802741E%22%5D&p_date=d_yesterday&p_date_range=2025-06-02--2025-06-16&p_gap_hours=540&p_site_id=GA6NAA84NK)
Low Voltage Badges
https://us.sitemetric.com/sites/VA28019978/reports/report-types/view/314
Site Report Exclusions - Where Are They Being Used
INSERT INTO site_report_exclusions
Setting up a
site_idexclusion by manually inserting a record into thesite_report_exclusionstable. The following reports support it: - Daily Report + - Headcount & Hours - Project Summary - Stationary Badges - Zone Detection Site Pulse does not show campus sites so the child site_id will not
insert into site_report_exclusions (site_id, rule_type, value, created_at, updated_at)
values (
'IN89963840',
'site_id',
'AB12345678', -- replace this with the new site_id
now(),
now()
)
Subcontractor Weekly Report
This can also be cloned but would still need to make the parameters static (sitemetric_id, days, etc)
Daily Company Totals
- [https://redash.sitemetric.com/dashboards/18510-campus---subcontractor-report---date-range---2025-04-24?p_company_id=["BQ7PCMP5GR"]&p_date_range=d_last_week&p_dates_to_exclude=["2024-12-25"]&p_day_numbers=["0"%2C"1"%2C"2"%2C"3"%2C"4"%2C"5"%2C"6"]&p_site_id=WA64849104&p_sitemetric_id=["All"]](https://redash.sitemetric.com/dashboards/18510-campus---subcontractor-report---date-range---2025-04-24?p_company_id=%5B%22BQ7PCMP5GR%22%5D&p_date_range=d_last_week&p_dates_to_exclude=%5B%222024-12-25%22%5D&p_day_numbers=%5B%220%22%2C%221%22%2C%222%22%2C%223%22%2C%224%22%2C%225%22%2C%226%22%5D&p_site_id=WA64849104&p_sitemetric_id=%5B%22All%22%5D)
-- Subcontractor Weekly Report
-- You'll need to change the company_id and all the other parameters (except the site_id)
SELECT clone_dashboard(id, 'PAAMV78AG8') FROM dashboards_by_tags('template,310531187')
Text Message Alert Documentation
This is the text messaging alert documentation we have. Neither is very clear atm.
https://www.notion.so/go-sitemetric/Text-Email-Alerts-Notifications-193fc5f52f208041a979c04f8daf05b4?pvs=4
https://www.notion.so/go-sitemetric/Text-Messaging-Scan-Notification-System-11cfc5f52f208091a9fae9555ae132c8?pvs=4
Equipment & Zone Site Deployments
For getting an excel file of all zones and equipment at a site. Good for giving to field techs when they have report requests that require many different zones or sensors. Ie, easier to copy and paste the ids from an spreadsheet than a PDF.
Scheduled Roll Call Report using zones
-- Roll Call Report
SELECT clone_dashboard(id, 'TN88426031') FROM dashboards_by_tags('template,760282893')
[https://redash.sitemetric.com/dashboards/21196-roll-call-report?p_date=d_now&p_detection_zone_id=["YXHFGUBYF6"]&p_end_hr=07&p_end_min=00&p_site_id=GA27364899&p_start_hr=06&p_start_min=30&p_w88829_end_hr=07&p_w88829_end_min=00&p_w88829_start_hr=06&p_w88829_start_min=30&p_w88830_end_hr=07&p_w88830_end_min=00&p_w88830_start_hr=06&p_w88830_start_min=30&p_w88831_end_hr=00&p_w88831_end_min=00&p_w88831_start_hr=00&p_w88831_start_min=00](https://redash.sitemetric.com/dashboards/21196-roll-call-report?p_date=d_now&p_detection_zone_id=%5B%22YXHFGUBYF6%22%5D&p_end_hr=07&p_end_min=00&p_site_id=GA27364899&p_start_hr=06&p_start_min=30&p_w88829_end_hr=07&p_w88829_end_min=00&p_w88829_start_hr=06&p_w88829_start_min=30&p_w88830_end_hr=07&p_w88830_end_min=00&p_w88830_start_hr=06&p_w88830_start_min=30&p_w88831_end_hr=00&p_w88831_end_min=00&p_w88831_start_hr=00&p_w88831_start_min=00)
Weekly Total Zone Hours
- - Shows where the most time was spent -- Moved scanners to a separate report because the hours spent in one entrance or exit scanner zone aren't relevant to zones. And Entrance to Exit hours plus individual zone hours will inflate the number Tabs: Total Zone Hours Daily Zone Hours Daily Worker Zone Hours
Unflagged Report
Some sites require the customer to “unflag” from workforce before approving site access. These reports join with the audit table to track who unflags a worker registration
Date Range
https://redash.sitemetric.com/queries/5673/source?p_date_range=d_last_7_days&p_site_id=VA14563963
Date
JSON Form Reports
Use this query to get a list of keys used
SELECT DISTINCT jt.key_name
FROM form_responses,
JSON_TABLE(
JSON_KEYS(data),
'$[*]' COLUMNS(key_name VARCHAR(255) PATH '$')
) AS jt
WHERE form_id = '1RB4C6HT4W';
keys:
time
notes
submitter_name
systems_gallery_number
All doors are closed and locked
To check one form field
SELECT JSON_EXTRACT(data, '$."safety_sticker"') AS safety_sticker FROM form_responses WHERE form_id = 'AWAMV4VK2A'
-- Sample Report
WITH site_timezones AS (
SELECT
-- sitemetric_id AS site_id,
timezone
FROM
sites
WHERE
sitemetric_id = 'VA1CDKE44Z'
)
SELECT
REPLACE(JSON_EXTRACT(fr.data, '$."time"'), '"', '') AS TIME,
UPPER(REPLACE(JSON_EXTRACT(fr.data, '$."All doors are closed and locked"'), '"', '')) AS "ALL DOORS CLOSED & LOCKED",
REPLACE(JSON_EXTRACT(fr.data, '$."notes"'), '"', '') AS NOTES,
REPLACE(JSON_EXTRACT(fr.data, '$."submitter_name"'), '"', '') AS NAME,
CONCAT(CONCAT(DATE_FORMAT(CONVERT_TZ(created_at, '+00:00', st.timezone), '%Y-%m-%d'), ' @ '), DATE_FORMAT(CONVERT_TZ(created_at, '+00:00', st.timezone), '%h:%i %p')) AS "FORM SUBMITTED",
GROUP_CONCAT(
CONCAT(
'Download'
) SEPARATOR '
'
) AS ATTACHMENTS
FROM
form_responses fr
INNER JOIN attachments a ON a.resource_id = fr.id
CROSS JOIN site_timezones st
WHERE
form_id = 'HZ23Z828U0'
GROUP BY
fr.id, fr.data, fr.created_at, st.timezone
ORDER BY
"SUBMITTED DATE" DESC,
"SUBMITTED TIME" DESC;
Key Fob Report
https://redash.sitemetric.com/dashboards/21277-key-fob-report
Mustering Report
https://redash.sitemetric.com/queries/6336
https://redash.sitemetric.com/queries/6336/source
Zone Headcount and Hours with PII remove
Google Trade Worker Zone Hours
https://redash.sitemetric.com/queries/6369/source?p_date=2025-06-24&p_site_id=IN98737034
API Key: km3fzElAnnwehpSQvSNwRm6IomcW0x5PfKa0JHH4
Google Zone Headcount and Hours Roll-up
https://redash.sitemetric.com/queries/6368
API Key: rJV8k6YjS0C2Ic0XD1xcIyBZ97WpNXlrfumN3Elm
Microsoft Trade Worker Zone Hours
https://redash.sitemetric.com/queries/6370/
API Key: B4nn5aOiGfBS5qUQMSXIhIlkixtgqXOEreze1Chp
Using API Endpoints to Retrieve Redash Query Results
Trade Report Dashboard
https://redash.sitemetric.com/dashboards/21597-trade-report
Fatigue Report (Ryan Companies request)
Want report/notifications sent of all worker onsite today that have crossed any of the 3 thresholds:
- Onsite > 10 consecutive days
- Total hours for the past 7 days >= 50 hours
- Total hours for the past 30 days >= 200 hours
Challenges that arise from not enough sensors: 1. 6 hour gaps separates worker hours who are onsite for 8 straight hours but only detected at the gates 2. 10 hour gaps fixes challenge #1 3. But then a 10-hour gap combines shifts where a worker scans out at 11:30 PM but then comes back to work at 5 AM. 1. These examples inflate hours that are either slightly higher or are so high they fall into the stationary category and are excluded entirely.
https://redash.sitemetric.com/dashboards/21828-fatigue-report?p_date_range=d_last_30_days
Generic Reports
Moved. See
Generic Reports
Signatures
CONCAT('data:image/png;base64,', REPLACE(JSON_EXTRACT(fr.data, '$."visitorSignature"'), '"', '')) AS SIGNATURE
Example: https://redash.sitemetric.com/queries/6455/source
Customer Sites List
https://redash.sitemetric.com/queries/6454/source
Zone Equipment List
For adding a list of zone equipment to a daily report
https://redash.sitemetric.com/queries/6513/source?p_site_id=CAB3AV2KDY
Muster/Rollcall/Stand-down Reports
Has parameters for date, start/end time, zone_id
https://redash.sitemetric.com/dashboards/23730-roll-call-report?p_date=2025-07-17&p_detection_zone_id=%5B%22X2CCDNQ91Z%22%2C%22E3X12X5NJF%22%5D&p_end_hour=12&p_site_id=NV17166429&p_start_hour=10
-- Roll Call Report with zone, date, time
SELECT clone_dashboard(id, 'TX12859380') FROM dashboards_by_tags('template,1394963170')
Worker Registrations
https://redash.sitemetric.com/queries/6566?p_date=d_yesterday&p_site_id=GA89382519
Fatigue and Safety Reports
`Fatigue Assessment Report` List of flagged workers who meet any of the following: - Onsite for 13 or more consecutive days - Onsite for 59+ hours in the past 7 days - Onsite for 259+ hours in the past 30 days `Safety Compliance Report` Covers any company whose average daily headcount (Mon–Fri) exceeds 25. Includes: - Whether they meet the required 25:1 Worker-to-Safety Officer ratio - Count of onsite Safety Officers (must have Safety Officer trade and OSHA 30+) - Safety Coverage Score: % of time a required Safety Officer was onsite when workers were present
Fatigue Assessments Report:
https://redash.sitemetric.com/dashboards/21828-fatigue-assessments-report?p_date_range=d_last_30_days&p_site_id=GA37493173
Safety Compliance Report:
https://redash.sitemetric.com/dashboards/23317-safety-compliance-report?p_date_range=d_last_7_days&p_site_id=GA37493173
INSERT INTO site_companies – TRADES
-- EXAMPLE:
/*
====================
1. This will INSERT companies that are not already in site_companies
====================
*/
INSERT INTO site_companies (site_id, company_id, parent_id, primary_id, trade, created_at, updated_at, deleted_at)
SELECT co.site_id, co.company_id, co.parent_id, co.primary_id, trade, co.created_at, co.updated_at, co.deleted_at
FROM (
SELECT 'VA27826262' AS site_id, '274D8AEC8F' AS company_id, '274D8AEC8F' AS parent_id, '274D8AEC8F' AS primary_id, trade AS 'Electrical', NOW() AS created_at, NOW() AS updated_at, NULL AS deleted_at UNION ALL
SELECT 'VA27826262', 'B50452324B', 'Sitework & Utilities', NOW(), NOW(), NULL UNION ALL
SELECT 'VA27826262', 'A93B4B20F1', 'Doors, Frames & Hardware', NOW(), NOW(), NULL UNION ALL
SELECT 'VA27826262', 'A7ABDFBEB5', 'Elevator', NOW(), NOW(), NULL
) co
WHERE NOT EXISTS (
SELECT 1 FROM site_companies sc
WHERE sc.site_id = co.site_id
AND sc.company_id = co.company_id
AND sc.deleted_at IS NULL
);
/*
====================
2. Use this to UPDATE multiple company trades that are already in site_companies
but do not have a trade assigned
====================
*/
UPDATE site_companies sc
JOIN (
SELECT 'VA27826262' AS site_id, '274D8AEC8F' AS company_id, 'Electrical' AS trade, NOW() AS updated_at UNION ALL
SELECT 'VA27826262', 'B50452324B', 'Sitework & Utilities', NOW() UNION ALL
SELECT 'VA27826262', 'A93B4B20F1', 'Doors, Frames & Hardware', NOW() UNION ALL
SELECT 'VA27826262', 'A7ABDFBEB5', 'Elevator', NOW()
) updates
ON sc.site_id = updates.site_id
AND sc.company_id = updates.company_id
SET
sc.trade = updates.trade,
sc.updated_at = updates.updated_at;
Trade Reports (+ API Documentation)
Weekly Subcontractor Headcount & Hours
Generic report with company_id & sitemetric_id parameters
[https://redash.sitemetric.com/dashboards/23915-weekly-subcontractor-headcount-hours?p_company_id=["All"]&p_date_range=d_last_week&p_site_id=IN89963840&p_sitemetric_id=["All"]](https://redash.sitemetric.com/dashboards/23915-weekly-subcontractor-headcount-hours?p_company_id=%5B%22All%22%5D&p_date_range=d_last_week&p_site_id=IN89963840&p_sitemetric_id=%5B%22All%22%5D)
https://us.sitemetric.com/sites/WAH62J7775/reports/report-types/view/397
Weekly Worker Report
Generic report with company_id & sitemetric_id parameters
https://redash.sitemetric.com/dashboards/23916-weekly-worker-report?p_company_id=%5B%22All%22%5D&p_date_range=d_last_week&p_site_id=VA23501290&p_sitemetric_id=%5B%22MCR8U1FXWG%22%5D
https://us.sitemetric.com/sites/VA23501290/reports/report-types/view/398
Submitted Form
https://us.sitemetric.com/forms/{{ @ }}?r={{ id }}
List of a Parent's Children Sites
https://redash.sitemetric.com/queries/5022?p_parent%20site_id=IA44937699
Updated Recursive site_ids for Campus
WITH RECURSIVE -- Only keep recursive if there's recursion later on in the script
site_ids as (
SELECT site_id
FROM (
SELECT DISTINCT(site_id) AS site_id
FROM data.site_hierarchy_view
WHERE site_id = '{{site_id}}'
UNION
SELECT child_id AS site_id
FROM data.site_hierarchy_view
WHERE site_id = '{{site_id}}'
) AS combined)
Creating a link to a completed form (closest thing to a PDF version of a completed form)
https://redash.sitemetric.com/queries/6889?p_form_id=WWHMABH8HF&p_site_id=CA15159060
Bulk update redash dashboard tags
[](https://redash.sitemetric.com/queries/6902/source?p_dashboard_id=25900)
Update redash dashboard tags - SITE_ID hardcoded into query https://redash.sitemetric.com/queries/7025/source?p_dashboard_id=26501&p_new_tag=VA08061853&p_new_tags=%5B%22VA62056789%22%2C%22VA63370387%22%2C%22VA87140862%22%2C%22SC00356893%22%2C%22TX43259035%22%5D
Update redash dashboard tags - SITE_ID with Dropdown
https://redash.sitemetric.com/queries/7024/source?p_dashboard_id=26503&p_new_tag=VA08061853&p_new_tags=%5B%22VA62056789%22%2C%22VA63370387%22%2C%22VA87140862%22%2C%22SC00356893%22%2C%22TX43259035%22%5D
Update redash dashboard tags - One SITE_ID
https://redash.sitemetric.com/queries/7023/source?p_dashboard_id=26503&p_new_tag=VA08061853
Counting Buildings per Campus
http://redash.sitemetric.com/queries/6951/source
Site Billing Dashboard for accounting
https://us.sitemetric.com/sites/US81228450/reports/27499?url=https%3A%2F%2Fus.sitemetric.com%2Freports%2Fdashboard%2F27499%3Fembed%3Dinternal%26p_site_id%3DUS81228450%26p_date%3Dd_now%26p_headcount_threshold%3D10%26p_headcount_date_range%3D30&name=Billing+Start+Date+with+Headcounts
Company Dropdown format
Turner: MDN06 NC57958796 https://us.sitemetric.com/api/v3/redash/query/5825/rows?api_key=pA851BaWpySfynQlVqk1RxkYWDsozVDMal5FWsbA
custom_data and custom_fields tables
https://sitemetric.slack.com/archives/C08V7S85K88/p1760450608276649
From Jackson:
First, create the row in the "custom_fields" table that will define this field. Values for that below: -
created_at,updated_at,deleted_at(null),id- Autogenerated -customer_id- Customer id of Microsoft -custom_id- Custom id that uniquely identifies this field. Can be generated with the generate_id() function -name- Something like "worker_site_title" -description- Descriptor of what the field is representing. I'd also describe how this data would get joined to the "worker_site_access" table in here -resource_type- "worker_site_access_view" Then, we populate the "custom_data" table: -created_at, updated_at, deleted_at (null) - Autogenerated -custom_id- The custom id that was created in the custom_fields table -resource_id- This'll get a bit wonky, but it'll work. Make this the concat of theworker_site_access_view(edited)sitemetric_idandworker_id. So if you have a worker withsitemetric_idof 'L86LP6LJVX' inworker_site_access_viewwith asite_idof 'MD30743307', then the field would be 'L86LP6LJVXMD30743307'. Unfortunately we can't do just the unique id from worker_site_access_view because that can get superseded by later worker_site_accesses for a specific worker. -value- Worker title on that site, e.g. 'Plumber' So then when you need to retrieve worker titles for a specific site, you can run something like this:
SELECT
wsa.sitemetric_id,
wsa.site_id,
cd.value AS worker_site_title
FROM worker_site_access wsa
INNER JOIN custom_data cd
ON cd.resource_id = CONCAT(wsa.sitemetric_id, wsa.site_id)
WHERE
cd.deleted_at IS NULL
AND wsa.deleted_at IS NULL;
Returns:
Compare Static site_id with tags
To make sure there are no dashboards with static site_ids that do not match the site_id tag. There are a few remaining but they are demo dashboards.
https://redash.sitemetric.com/queries/7225/source
These are reports that can be used for any site. They include a site_id tag. When viewed in dashview, the site_id dropdown will not be visible, and the system will automatically use the current site_id from the app.
Internal reports will display the site_id dropdown only if the user has access to reports from the internal reports site.
Generic Dashboards
- Just need to add
site_idtag to show in-app.
Generic Dashboards
TODO: We need to clean this up and organize it a little better. Not sure how yet.
*Do these go in the list above? I guess they should? I don’t know why they weren’t there already.*
`Monthly Headcount and Hours`
https://us.sitemetric.com/sites/TXX5WM16KZ/reports/report-types/view/368
`Weekly Headcount and Hours`
https://us.sitemetric.com/sites/TXX5WM16KZ/reports/report-types/view/369 With site_id parameter
dash.us.sitemetric.com With site_id parameter
https://us.sitemetric.com/sites/WAH62J7775/reports/report-types/view/397 With company_id & sitemetric_id parameters
dash.us.sitemetric.com With company_id & sitemetric_id parameters
`Daily Scan Report` (with Daily Zone Hours from sensors)
https://us.sitemetric.com/sites/MN10139625/reports/report-types/view/353
Trade Reports
These Trade Reports (created for Roqeeb’s google pilots sites) are all generic now. We need to make campus-enabled ones too. (Not hard, just haven’t done it yet.)
- Trade Worker Zone Hours — Link: dash.us.sitemetric.com; Dashview: Yes; Schedulable: Yes; Scope: Site
- Trades by Zone — Link: dash.us.sitemetric.com; Dashview: Yes; Schedulable: Yes; Scope: Site
- Trade Workers - Daily Heatmap — Link: dash.us.sitemetric.com; Dashview: Yes; Schedulable: Yes; Scope: Site
Dashboards needing to be cloned and parameters manually set to static
⁉️ But… if you have to clone it, then it’s not *generic* right?
/*
Portfolio Dashboards
*/
-- Portfolio Sites Monthly Headcount << Set owner_id to static >>
SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,513197122')
-- Portfolio Sites Monthly Hours << Set owner_id to static >>
SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,767241542')
-- Portfolio Compannies Monthly Headcount & Hours << Set owner_id to static >>
SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,333117014')
-- Portfolio Compannies Directory << Set owner_id to static >>
SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,881714844')
-- Portfolio Sites Weekly Headcount << Set owner_id to static >>
SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,108393844')
-- Portfolio Sites Weekly Hours << Set owner_id to static >>
SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,904025682')
/*
Other Dashboards
*/
-- Single Scan
SELECT clone_dashboard(id, 'PAAMV78AG8') FROM dashboards_by_tags('template,58423891')
-- Perimeter Check Dashboard <
> -- One form and QR code with checkpoint dropdown SELECT clone_dashboard(id, 'CA15159060') FROM dashboards_by_tags('template,745305981') -- Link to dropdown query: https://dash.us.sitemetric.com/queries/5026 -- Security Log Patrol Action Report <
> -- One form and multiple QR codes that populate the checkpoint selection SELECT clone_dashboard(id, 'CA15159060') FROM dashboards_by_tags('template,403243097') -- Link to dropdown query: https://dash.us.sitemetric.com/queries/5026 -- Manage Worker Labels << Set form_id to static >> SELECT clone_dashboard(id, 'KS56346263') FROM dashboards_by_tags('template,594430044') -- Link to dropdown query: https://dash.us.sitemetric.com/queries/5026 -- Daily Report that includes a visitor form << Set the form_id to static >> SELECT clone_dashboard(id, 'UT61663758') FROM dashboards_by_tags('template,320675079')
https://dash.us.sitemetric.com/dashboards/25581-company-directory---hierarchies?p_site_id=PAAMV78AG8
Generic Report Types (Scheduled email reports)
We now have a series of trade reports that can be accessed via an API endpoint, however I want to phase that out and have them use a different data delivery mechanism if possible.
Now we have the ability to dump the data into S3 daily, with Azure as an upcoming option.
There are two ways to access this data:
- Trade Reports API (I’m trying to deprecate this; hardly anyone uses it anyway, and possibly no one uses it)
- Trade Reports Data Delivery via S3/Azure Blob Storage
Trade Reports - BigQuery Data Transfer Setup
Report Descriptions
Trade Worker Hours
Includes every individual worker’s hours during the specified time frame, by day.
Trade Worker Times
Includes
Trade Summary
Shows the total hours that trades spent onsite during the specified time range.
Trade Zone Summary
Shows the total hours that trades spent in each zone during the specified time range.
Trade Reports API
*I’m trying to deprecate this in favor of the Data Delivery method via S3/Azure Blob Storage.*
They all have the exact same parameters. And every request requires authentication. You can learn about our authentication here: https://us.sitemetric.com/docs.html#auth
In short: POST to /auth/token with your client_id and client_secret, and you’ll get back your bearer token, which you will then use to make further authenticated requests.
⚠️ The queries that power these reports are quite hefty. If you get timeouts, you may need to get smaller chunks. For example, you may have to get the data one day at a time.
Required Parameters
site_id
Replace with the Site ID of the project site; this is replaced in the URL itself; it is not a query string parameter.
Optional Query String Parameters
companyIds
?companyIds=AB12345678,XY12345678
Default: No filters
Filters the data by the specified Company IDs. A comma separated list.
endDate
?endDate=2025-08-04
Default: Yesterday’s date
Specifies an end date for the date range. See startDate.
excludePII
?excludePII=true
Default: false
Excludes name and sitemetric_id from the data.
hashPII
?hashPII=true
Default: false
Creates a unique AnonWorkerId for every worker, so that you can still group detections by an individual worker without knowing who they are.
"anonWorkerId": "12342dda4ab1a67f",
page
?page=1
Default: 1
Which page of data you’d like to get. We use Link and X-Pagination headers to give you additional information about the paged results. Also see perPage.
Link:
; per_page="25"; rel="first prev",
; per_page="25"; rel="next",
; per_page="25"; rel="last" X-Pagination: {"currentPage":1,"perPage":25,"total":1797,"lastPage":72}
perPage
?perPage=100
Default: 25
The number of items to return per page. Also see page.
startDate
?startDate=2025-08-01
Default: Yesterday
Specifies a start date for the date range. See endDate.
titles
?titles=Electrician,Plumber
Default: No filters
Filters the data by the specified titles. A comma separated list.
trades
?trades=Electrician,Plumber
Default: No filters
Filters the data by the specified trades. A comma separated list.
zoneIds
?zoneIds=AB12345678,XY12345678
Default: No filters
Filters the data by the specified Zone Ids. A comma separated list.
Parameter Combinations
You can combine them all together as needed, like so:
?page=1&perPage=1000&companyIds=AB12345678&excludePII=true&hashPII=true
Trade Worker Hours
https://us.sitemetric.com/api/v3/reports/sites/{{site_id}}/trade-reports/worker-hours
Includes every individual worker’s hours during the specified time frame, by day.
[
{
"date": "2025-08-03",
"zone": "Exterior Field Office",
"zoneId": "XYF0G1FXZT",
"company": "ABC Technologies",
"companyId": "1BKPA6SWYS",
"trade": "Deliveries",
"title": "Delivery Driver",
"sitemetricId": "1AB2C3D4E5",
"name": "John Doe",
"totalHours": 7.95
}
]
Trade Worker Times
https://us.sitemetric.com/api/v3/reports/sites/{{site_id}}/trade-reports/worker-times
Includes
[
{
"date": "2025-08-03",
"zone": "Exterior Field Office",
"zoneId": "XYF0G1FXZT",
"company": "ABC Technologies",
"companyId": "1BKPA6SWYS",
"trade": "Deliveries",
"title": "Delivery Driver",
"sitemetricId": "1AB2C3D4E5",
"name": "John Doe",
"inTime": "2025-08-03T06:00:54.000Z",
"outTime": "2025-08-03T13:55:25.000Z"
}
]
Trade Summary
https://us.sitemetric.com/api/v3/reports/sites/{{site_id}}/trade-reports/trade-summary
Shows the total hours that trades spent onsite during the specified time range.
[
{
"trade": "Electrical",
"totalHours": 48.1,
"headcount": 2
}
]
Trade Zone Summary
https://us.sitemetric.com/api/v3/reports/sites/{{site_id}}/trade-reports/trade-zone-summary
Shows the total hours that trades spent in each zone during the specified time range.
[
{
"trade": "Electrical",
"zone": "Break Tent",
"zoneId": "W5REJ8EZDP",
"totalHours": 6.13,
"headcount": 2
},
{
"trade": "Electrical",
"zone": "Exterior Bathroom Building",
"zoneId": "X3DC8147HJ",
"totalHours": 3.65,
"headcount": 1
}
]
We can access redash data by using special endpoints.
TODO: Add documentation for the other ways we can do this, or how to get these encrypted query IDs (use the Encrypt endpoint — see Postman).
Here are some examples.
Google Sites - Zone Headcount Hours
https://redash.sitemetric.com/queries/6368/source
api_key: rJV8k6YjS0C2Ic0XD1xcIyBZ97WpNXlrfumN3Elm query_id: 6368 encrypted query_id: b8wBN6OyQYgLJOzGcebjpw==.ocnvL9ZKDtzyxC2us7joyg==
curl --location 'https://us.sitemetric.com/api/v3/dash/queries/b8wBN6OyQYgLJOzGcebjpw==.ocnvL9ZKDtzyxC2us7joyg==/results?api_key=rJV8k6YjS0C2Ic0XD1xcIyBZ97WpNXlrfumN3Elm' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ...' \
--data '{
"parameters": {}
}'
Google Sites - Trade Worker Zone Hours
https://redash.sitemetric.com/queries/6369/source api_key: km3fzElAnnwehpSQvSNwRm6IomcW0x5PfKa0JHH4 query_id: 6369 encrypted query_id: J_f9MJ-Fpw8Gnb9nlxHAUA==.u-EYrzcomuvlri2GtPE_Sg==
curl --location 'https://us.sitemetric.com/api/v3/dash/queries/J_f9MJ-Fpw8Gnb9nlxHAUA==.u-EYrzcomuvlri2GtPE_Sg==/results?api_key=km3fzElAnnwehpSQvSNwRm6IomcW0x5PfKa0JHH4' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ...' \
--data '{
"parameters": {}
}'
Microsoft Sites - Trade Worker Zone Hours
https://redash.sitemetric.com/queries/6370/source api_key: B4nn5aOiGfBS5qUQMSXIhIlkixtgqXOEreze1Chp query_id: 6370 encrypted query_id: QJ03gO6IuC-mZRQ2wrfXKA==.rm9D9UrKURLYjiipmgbJuw==
curl --location 'https://us.sitemetric.com/api/v3/dash/queries/QJ03gO6IuC-mZRQ2wrfXKA==.rm9D9UrKURLYjiipmgbJuw==/results?api_key=B4nn5aOiGfBS5qUQMSXIhIlkixtgqXOEreze1Chp' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ...' \
--data '{
"parameters": {}
}'
*Accurate as of 4/21/2025*
This table shows the report and which exclusions are in place:
DailyHoursTable (Not retroactive) — Companies: No; Zones: Yes; Sites: No; Date: No; Day of Week: No; Supports site_companies: No; Campus Enabled: NoSessionsTable (Not retroactive) — Companies: No; Zones: Yes; Sites: No; Date: No; Day of Week: No; Supports site_companies: No; Campus Enabled: No- Daily Report+ Dashboard: 15760 PDF query: 6007 — Companies: Yes; Zones: Yes; Sites: Yes; Date: No; Day of Week: No; Supports site_companies: Yes; Campus Enabled: Yes
- Headcount & Hours — Companies: Yes; Zones: Yes; Sites: Yes; Date: Yes; Day of Week: Yes; Supports site_companies: No; Campus Enabled: Yes
- Project Summary — Companies: Yes; Zones: Sort of**; Sites: Yes; Date: Yes; Day of Week: Yes; Supports site_companies: No; Campus Enabled: Yes
- Real-Time Location — Companies: Yes; Zones: No; Sites: No; Date: No; Day of Week: No; Supports site_companies: No; Campus Enabled: Yes
- Site Access — Companies: Yes; Zones: N/A; Sites: No; Date: N/A; Day of Week: N/A; Supports site_companies: No; Campus Enabled: No
- Site Pulse — Companies: Yes; Zones: Yes; Sites: No; Date: No; Day of Week: No; Supports site_companies: No; Campus Enabled: Yes
- Zone Headcount & Hours — Companies: Yes; Zones: No; Sites: No; Date: No; Day of Week: No; Supports site_companies: No; Campus Enabled: Yes
⚠️ If custom queries are used, you’d have to check those individually.
** = Sort of; Project Summary uses DailyHours which would start filtering them out from the time that exclusion was added, but it won’t be retroactive.