From a holder of two BCSP credentials · shared person-to-person

I passed the CHST yesterday. Then I looked hard at my own badge.

On 07/29/2026 I earned the CHST, which gave me a second BCSP badge and a second reason to read that page closely. Six things, every one observed on my own two badges and inside my own account, every one with the fix written out below. No other holder's badge was opened, and nothing was tested that isn't mine.

STS
Safety Trained Supervisor®
STS-18969 · certified 01/29/2026
ACTIVE
CHST
Construction Health and Safety Technician®
CHST-24015 · certified 07/29/2026
ACTIVE

Both verifiable at badge.bcsp.org: STS · CHST

The one that costs you the most

Passing the exam is the proudest day in a certificant's year, and the first thing they do is share the badge.

Finding 1 · the share card

Every badge page is titled "BCSP Badge" and has no share card, so posting it produces a blank link.

The only meta tag on the page is viewport. There is no og:title, no og:image, no twitter:card, and the <title> is the same three words for every holder of all ten credentials. Paste a badge into LinkedIn, a text message, Slack, or an email signature and it renders as a bare blue URL: no name, no credential, no seal, no BCSP.

$ curl -s "https://badge.bcsp.org/?e=<my CHST token>" \ | grep -oiE '<meta[^>]*(og:|twitter:)[^>]*>' | wc -l 0 $ curl -s "https://badge.bcsp.org/?e=<my CHST token>" | grep -oiE '<title>[^<]*' <title>BCSP Badge

Every certificant who shares a badge is doing your marketing for free, and the link arrives carrying nothing. Ten credentials, tens of thousands of holders, every share landing blank.

FixPaste this into the badge template's <head>. Field names are illustrative; the values are already on the page.
<!-- per-badge identity: replace the fixed "BCSP Badge" title -->
<title>{{holder_name}} · {{cred_acronym}} · BCSP</title>
<meta name="description"
      content="{{holder_name}} holds the {{cred_full_name}} ({{cred_acronym}}),
               certification {{cert_number}}, issued by the Board of Certified
               Safety Professionals. Status: {{status}}.">

<!-- the share card -->
<meta property="og:type"        content="profile">
<meta property="og:site_name"   content="Board of Certified Safety Professionals">
<meta property="og:title"       content="{{holder_name}} · {{cred_acronym}}">
<meta property="og:description" content="{{cred_full_name}} · Certification {{cert_number}} · {{status}} · Accredited by ANAB to ISO/IEC 17024">
<meta property="og:url"         content="https://badge.bcsp.org/?e={{token}}">
<meta property="og:image"       content="https://badge.bcsp.org/share/{{token}}.png">
<meta property="og:image:width"  content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card"       content="summary_large_image">
<meta name="twitter:title"      content="{{holder_name}} · {{cred_acronym}}">
<meta name="twitter:description" content="{{cred_full_name}} · Certification {{cert_number}} · {{status}}">
<meta name="twitter:image"      content="https://badge.bcsp.org/share/{{token}}.png">

The one piece that needs building is /share/{{token}}.png: a 1200×630 card with the seal you already own, the holder's name, the credential, and the certification number. It is one server-side render, cached. Everything above it is copy and paste.

Five more, from inside the account

These are the ones you only meet by holding the credential rather than issuing it.

Finding 2 · the photo

The profile editor will not let me add a photo, so every badge shows the same placeholder.

There is a holder profile editor at badge.bcsp.org/profile_editor.php. Signed in to my own account, I cannot set a photo through it. The badge therefore renders profile_images/profile.jpg, a relative path with no holder identifier in it. Requested against my CHST badge's session, my STS badge's session, and with no session at all, the bytes come back identical: 9,747 bytes, MD5 42a74ebe3b079e5efacd5cc9cbbd8396, a generic blue silhouette served to every credential holder you have.

$ md5 -q img_from_chst_session.jpg img_from_sts_session.jpg img_no_session.jpg 42a74ebe3b079e5efacd5cc9cbbd8396 42a74ebe3b079e5efacd5cc9cbbd8396 42a74ebe3b079e5efacd5cc9cbbd8396
FixMake the editor's photo control actually write, and key the stored image to the credential record rather than to one shared filename. Until that ships, render the frame only when a photo exists: an empty frame reads better than a stranger's silhouette on my credential.
Finding 3 · the employer

I cannot change my organization in the profile editor, and no employer reaches the badge.

Signed in to badge.bcsp.org/profile_editor.php as I write this, I cannot change the organization or employer I work for. Downstream of that, the words "employer" and "company" appear zero times in the rendered badge markup, so no employer reaches the badge whatever the editor is meant to do.

The CHST's own eligibility is built on construction site experience with an employer, and the badge cannot name one. For anyone reading a badge to make a hiring or site-access decision, the employer is the second question after the credential itself, and holders change employers far more often than they recertify.

FixMake the editor's organization control write and persist, and render it on the badge as an optional "Current employer" shown only when set. Blank beats wrong.
Finding 4 · the word "Expires"

The annual renewal date is labelled "Expires", and the note beside it explains something else.

My CHST was certified 07/29/2026 and the badge reads "Expires 12/31/2026". Two rows below, RECERTIFICATION CYCLE 07/29/2026 - 06/30/2032. There is a note next to that label and it deserves credit: it explains that dates may show as past due without the credential being invalid, that recertification carries a grace period to July 31, and that renewal payments carry one to March 1.

What the note never says is what the December date actually is. My dues are paid and my credential runs to 2032, and my badge still leads with a date five months out under the word "Expires". Anyone reading it has to work out that "Expires" means the payment year, not the credential, and the note that is right there does not tell them.

FixLabel the field "Annual renewal due" and let "Expires" carry the recertification cycle end. Keep the note for the genuine edge cases. It is currently doing work the label should be doing.
Finding 5 · two credentials, two pages

Holding a second credential gives you a second disconnected page, not a fuller one.

My STS badge links my CHST badge as a second raw URL. There is no page that says "Brandon Kelly, BCSP credential holder: STS, CHST." A holder who has invested in more than one of your credentials has no single link that shows the whole investment, and the accumulation of credentials is exactly the story BCSP wants told.

FixOne holder page listing every active credential, with the individual badge pages kept as they are for direct links.
Finding 6 · nothing a machine can read

The badge carries zero structured data, so software cannot read the credential it exists to prove.

grep -c 'application/ld+json' on the badge returns 0. This is the same gap the findings page describes across the estate, and the badge is where it bites hardest: the badge holds exactly the right payload (status, number, issue date, recertification cycle, accreditation) in the one format only a human can use.

FixThe EducationalOccupationalCredential block is already drafted for you on the kit page, ready to paste into the same template.
Two findings are deliberately not on this page. One concerns how badge URLs are constructed. The other is a server-configuration detail visible on a public page of the badge application. Publishing either would not be responsible even on an unlisted page. Both are written up and yours the moment you ask, sent directly and privately, with no timeline and no conditions. Neither was tested against anything that is not mine, and I would not.
The honest case against all of it: the badge works. It loads fast, it says the true thing, it is served over HTTPS with no console errors, and the payload behind it is more complete than most credentialing bodies manage. Nothing here is a defect, nothing is urgent, and none of it will cost you a certificant this quarter. It is one observation: the badge is a marketing surface that currently does no marketing, on the single day each year a certificant most wants to show it off. Finding 1 alone is an afternoon.
Provisioned by EcoWealth · Digital Provisioning Protocol · provenance‑sealed