Article Guide Jump to a section 8 min read · 5 sections
Engage Share or leave a rating Copy, send, or respond when you finish

Leave A Rating

Another renovation week. The training page got the rewrite it had been quietly asking for, opinions got their own post type, and an EEAT audit on my own site turned up the kind of schema drift I’d flag in a client engagement and quietly hope they’d fix before I had to invoice for it. None of these were small jobs. Three of them are worth writing down because they map directly onto problems I see on other people’s installs.

The training page stopped hedging

The old training page led with Microsoft Office training and tucked WordPress in behind it. That ordering was an artifact of where the work came from five years ago, not where it comes from now. WordPress training is the senior offer, the one tied to media, education, and government clients who pay senior-developer rates. Office training is real and I still do it, but it’s the secondary track. The page was telling the wrong story.

So I rewrote it. WordPress leads. Microsoft training sits underneath as a distinct second track, with its own header treatment that doesn’t apologize for being there but also doesn’t compete for the visitor’s first thirty seconds. The day rate moved to $2,250 CAD, which is what an in-person training day actually costs when you account for prep, materials, travel, and the fact that you’re getting someone who has shipped this stuff at scale rather than someone reading from a vendor deck. Schema, seeders, internal copy references — all pulled into line with the new number. Half-measures on price are worse than honest pricing, because anyone running the math on your day rate against your bio is going to notice the gap.

The visual change matters more than I expected. The previous version used text badges for the two tracks; I swapped them for photo thumbnails — a person in front of the material, not a coloured rectangle with a label on it. The page reads differently now. Less brochure, more “here is the human who shows up and runs the room.” That’s the right tone for a service where the deliverable is, literally, me being in your office for a day.

The thing worth writing down is: when a service page leads with the wrong offering, you don’t fix it by giving the right offering more pixels. You reorder the entire narrative. The reader needs to land on the headline offer first, and every supporting element — copy hierarchy, image weight, schema, price anchoring — has to point at it. Anything less and you’ve just made the confusion more colourful.

Opinions now have their own post type

Here’s a problem I’ve been sitting on for months. I have opinions about WordPress, about code quality, about how to mentor a junior developer through their first real production incident. Those opinions were scattered across regular blog posts, mixed in with how-tos and weekly roundups, with no structural signal that they were stated positions rather than tutorials. A search engine reading my archive couldn’t tell the difference between “here is how I think about plugin licensing” and “here is how you install WP-CLI.” Both look like Article objects. Both get the same schema treatment.

So I built a Stances custom post type. Each stance is a single stated position on a single topic. The schema is Article with a SpeakableSpecification block — a stance is exactly the kind of content a voice assistant should be able to read aloud verbatim — plus an opinion flag and explicit mentions and subjectOf connections to the entities the position is about. Post meta tracks the position itself, my confidence level in it, and the last-reviewed date. An opinion from 2022 that I haven’t revisited isn’t the same artifact as one I stand behind today, and the date makes that visible.

The block pattern surfaces all of that to the reader: what the position is, how confident I am in it, when I last looked at it. That’s the part that matters more than the schema. A stance is a commitment, and commitments age. Hiding the freshness date because it might look bad is the kind of thing that erodes trust slowly and then all at once.

Ten stances seeded on dev. They’ll roll to production once I’ve reviewed each one with the question “would I still send a friend here if they were trying to make a decision on this topic?” If the answer is anything other than yes, the stance gets rewritten or held.

I audited my own EEAT and didn’t like everything I found

I ran the same EEAT audit on my own schema that I’d run on a client’s. Three findings came back, ranked the way I’d rank them in a client report.

P0: the Person schema and the LocalBusiness schema were citing different formats for the same employer. One used the full legal name, the other used the brand name. To a human reader those are obviously the same entity. To a knowledge graph trying to reconcile two nodes, they’re two different strings, and the graph either picks one and discards the other or refuses to merge them. Either outcome weakens the entity signal. I’d already centralized brand naming in copy; I hadn’t done the same for schema emitters.

P1: duplicate #business nodes. The theme was emitting a LocalBusiness object, and so was the site plugin. Two LocalBusiness objects for the same address on every page, fighting each other. The fix was to delete the theme-side emitter and let the plugin own the node, which is where it belongs anyway — schema for a business entity isn’t a theme concern.

P2: my MA credential year was wrong in one emitter. I cite the credential as evidence of depth, and the year is verifiable from the conferring institution. One file had 2010, the correct year is 2009. A one-character error, but the kind that costs more trust than the credential earns if someone actually checks. Fix: centralized the credential source so every emitter calls the same function. The author archive was also leaking a redirect, patched while I was in there.

The check is: if you cite a fact as evidence of authority, that fact has to be correct everywhere it appears and has to resolve to the same canonical value across every emitter on the page. An inconsistency between your structured data and your About page isn’t neutral — it’s a structured claim that you’re unreliable. Centralize the source. Don’t trust copy-paste between PHP files to stay accurate over years.

Also this week

  • Retired EmDash from the service layer. It’s a content-marketing article writing service, not a pillar offering, and the three remaining pages that listed it as a service got converted to blog posts. Redirects are in place. The case-studies archive now routes to portfolio, which is where it should have been pointing all along.
  • thisismyurl-login-support got a real security upgrade: a honeypot username trap (bots fishing for admin, root, administrator get caught), fail2ban-compatible log format, a brute-force sparkline in the admin UI, a TOTP compatibility shim for the Two Factor plugin, and a read-only REST endpoint for querying lockout state.
  • thisismyurl-webp-support 0.6126 ships AVIF output alongside WebP via <picture>, quality preset profiles (web, print, lossless), and a savings projection in dry-run mode. Fully internationalized.
  • thisismyurl-external-link-control added a weekly HEAD-check cron that raises an admin notice on dead links, plus a REST GET at /timu-elc/v1/inventory for domain-level link auditing.
  • Services and portfolio archives got trust strips, hero portrait parity, and FAQ layers. The blog category taxonomy dropped from 27 entries to 7 — 21 empty terms deleted via WP-CLI, 10 post titles updated to match what the posts actually are.
  • REST routes and the site plugin’s data layer moved out of the theme. Issue #363 had been sitting in the backlog as a cross-boundary violation for too long; theme code should deliver markup, not own data routing.
  • A Niagara landing page scaffolded at /niagara for the local market. New homepage hero portrait — the Niagara-era headshot — and a fresh testimonial seeded from a recent Google review.
  • Five security findings from an expert review, addressed. Blog mobile UX cleaned up: sidebar hierarchy, share sidebar redesigned to icon buttons, post dates corrected to canonical publish date, social titles aligned to the live post title.

The thread running through all of this is the same one from last week: the site is the portfolio. Every fix I work out here is one I’ll apply on a client install eventually, and the patterns I figure out on my own time are the ones I bring to paid engagements. A training page that hedges, opinions with no structural identity, credentials that don’t reconcile across schema — those are exactly the problems I get hired to find. Better to find them on mine first.

Last Reviewed

This article was last reviewed on May 11, 2026 for accuracy and relevance.