TDM Insights brand mark TDM Insights SEO & AI Advisory Book a diagnosis

Eight workstreams.
One of them was the website.

Cacao Boys makes hand painted bonbons onsite in Bala. Their site looked pleasant, could not be read by a search engine, could not be quoted by an assistant, and took 21 seconds to show a product on a phone. Replacing it took ten days.

  • 10 days from kickoff to the new site going live, day zero to day ten in the project record
  • 183 published products carried across and recategorised, counted in the live store
  • 79 of 79 URLs with search history kept alive through the platform move
  • 8 workstreams inside one rebuild, itemised in full at the end of this page

The build was ten days. The decision took longer.

The diagnostic recommended a patch and said plainly that none of this was a rebuild. Sixteen days later I withdrew that advice, because a page builder runtime sets a ceiling that tuning does not reach. Recommending a larger piece of work after advising against it is uncomfortable, and it was the right call. The diagnostic came first. The build began at kickoff, sixteen days later, so day zero below is kickoff.

  • DAY 0. Rebuild proposed, kickoff
  • DAY 2. Whole site on staging
  • DAY 7. Client review queue, 14 requests
  • DAY 10. Live
  • DAY 13. Measured

Whole site v0.5 stood up on password protected staging two days after kickoff. Everything after that was iteration against a live client review queue rather than a first draft.

The slowest page on the site became one of the fastest.

The product page is where the money is, and it was the worst page they had. A shopper on a phone waited 21.5 seconds to see the chocolate they had clicked. Bar length is load time, so shorter is faster.

Mobile load time on six pages, before and after the rebuild OLD SITE, SECONDS AND LIGHTHOUSE SCORE LIVE SITE 0s 5s 10s 15s 20s Product page 21.5s (33) 4.2s (80) Home 10.7s (61) 3.2s (93) Custom boxes 6.8s (62) 4.0s (87) About 7.6s (63) 5.1s (74) Shop 7.3s (63) 5.3s (74) Bonbons 5.8s (67) 5.3s (73)
Google PageSpeed Insights, mobile, median of three runs. Lighthouse score in brackets.
Measure Old site Live site
Product page desktop score4299
Shop and category desktop score8193 to 100
Cumulative layout shift, all pagesNot measured0
Accessibility range across pages79 to 9297 to 100

Shop and the bonbons category are the weakest live pages on mobile at 74 and 73. The heaviest single file on both is a 160KB third party analytics tag; blocking it in a controlled test recovered roughly a quarter of a second. Reported as a lead, not as an excuse.

A custom theme, with no page builder underneath it.

The photography was the strongest asset the business had, and it was sitting inside a stock theme that undercut it. BeTheme and Elementor were replaced with a purpose built design system, and the shop's own language was rewritten around what it actually sells: painted edible art, made in Bala, bought as a gift.

The rebuilt Cacao Boys homepage: the line Artisanal chocolate, handcrafted in Bala, over a photograph of a chocolate gift box
Home, live. The rebuilt homepage on Cacao Boys, captured from the live site.

Each category archive carries its own hero and its own opening copy rather than one generic line, so a shopper landing on Seasonal from search reads about seasonal chocolate. The hero images run on a seasonal rotator that shipped alongside the theme as a reusable plugin, so the shop can set up its own autumn and holiday takeovers without me.

The workstream that is easiest to underestimate.

A WooCommerce catalogue is a database, and this one had grown for three years without an owner: duplicated boxes, a merch tail longer than the chocolate range, and product images that cropped badly in the grid. It was the largest single workstream in the rebuild.

56Confections
71Merch
25Dipped
21Bonbons
10Seasonal
8Custom boxes

Merch is the longest row in the catalogue: 71 t-shirts and hats against 112 chocolate products, which is the imbalance the category restructure had to solve.

  • 135 products given a written short summary and a long form description in the shop's own voice
  • 175 product images re-squared with adaptive padding so grid crops stop cutting the chocolate
  • 60 nutrition labels reconciled against products, with a label to product map
  • 17 question and answer pairs written and marked up for search and assistants

Every bulk operation ran with a manifest and a one command restore. The image work never overwrote an original: each squared file was imported as a new attachment and the product's thumbnail repointed, with the previous value captured first.

A setting can be switched on and still do nothing.

A checkout audit was not in the brief. Rebuilding the templates meant reading the store configuration, and in three places that configuration did not match what the site was telling customers.

Shipping never configured.

THE SITE SAIDFlat $15 shipping within Canada.

THE STORE DIDFlat rates disabled. Zones had empty regions, so no rate could ever match.

THE FIXRebuilt as one Canada zone: free local pickup, $10 flat under $150, free over $150, calculated pre tax. The advertised $15 existed only in copy.

A free shipping threshold that did not exist.

THE BANNER PROMISEDFree shipping on orders of $100 or more.

WOOCOMMERCE ENFORCEDmin_amount = 150.

THE FIXShoppers were being offered a threshold the checkout would refuse. WooCommerce is now the single source of truth and the cart notice reads the live figure instead of hardcoding one.

A pickup rule that silently never fired.

THE RULE TARGETEDA shipping method titled "Flat Rate of $10 within Canada".

THE STORE'S METHOD WAS NAMED"Flat-rate shipping (Canada)".

THE FIXThe plugin matches on an exact title string, so the date exclusion was enabled, looked correct in the admin, and had never once applied.

Also closed at cutover: card payments flipped from test to live and verified server side, search engine visibility re-enabled so canonicals resolved sitewide, and order confirmation emails fixed after they were found failing domain authentication.

A platform move is where rebuilds quietly lose what they already had.

The redirect map was built from evidence rather than assumption, from three sources that each catch what the others miss.

The old site's own sitemap.

217 URLs the old site published, taken from its own sitemap rather than a crawl that could miss orphans.

A crawl.

Pagination, feeds and legacy category paths that were linked and live but never listed in the sitemap.

Sixteen months of Search Console history.

So the map was driven by what had earned a visit, not by what happened to exist.

That produced a 41 row map, of which ten rules run at the CDN edge and the rest are handled inside the theme. Six of the ten flatten the old product category base onto clean category URLs. The other four retire pages whose content moved: the old gallery folds into About, the menu into the cafe page, and the gifts and merch path becomes the merch path, which carried more search impressions than any other redirect in the map.

Verified after cutover Result
URLs with Search Console history still reachable79 of 79
Sitemap URLs requested individually, returning 200199 of 199
Sitemap URLs that redirect rather than resolve0
Legacy URLs still returning 404, none with traffic5, was 10

For a local shop, being quotable is the same problem as being findable.

The old site ran without an SEO plugin, so it had no descriptions, no controlled titles and no structured data beyond what WooCommerce emits by default. Customers who ask an assistant where to buy chocolate near Bala had nothing to be pointed at.

Signal Old site Live site
Meta descriptions0 sitewideUnique on every page
Pages with no H181 of 1500
Title lengthUp to 101 chars47 to 51 chars
Schema types per pageProduct only12 to 22
Google's Lighthouse SEO scoreNot comparable100 on every page

Answer engine readiness on the category page.

Signal, scored 0 to 100 Before After
Answer first structure6082
Extractable facts6880
Entities and definitions8588
Question coverage5555
Citations4040
Scannable formatting8286
Structured data readiness7880

The site average moved from 34, the not citable band, to 81. The bonbons category was the last page in the partial band and cleared it after one plain language paragraph went in above the product grid. Question coverage did not move, because that signal only responds to an FAQ block, which the category and product pages still do not carry.

Everything that shipped.

Fifty line items, grouped by the part of the store they touched.

Theme and front end, days 0 to 9

  • Custom WordPress theme replacing BeTheme and Elementor
  • Design system tokens, type scale and component CSS
  • Homepage: hero, collection grid, craft, events, visit, FAQ
  • Shop archive with category tabs and per category hero copy
  • Product page redesign with spec panel and gallery
  • Build a box builder skin across six box sizes
  • Cart and checkout restyled inside the theme wrapper
  • About, in store cafe, events, contact and wholesale pages
  • Mobile navigation, search panel and footer directory
  • Seasonal hero rotator shipped as a reusable plugin

Catalogue and product data, days 2 to 8

  • 135 products given a short summary and a long description
  • Per product SEO titles and meta descriptions
  • Category restructure and shop tab reordering
  • Assorted boxes merged into a single Custom Boxes category
  • 175 product images re-squared with adaptive padding
  • Image alt text completed across the grids
  • 60 nutrition labels reconciled to products
  • Allergen lines drafted for merchant verification
  • Wholesale gating at a $300 and five piece minimum
  • Reversible manifests and one command restores throughout

Commerce and configuration, days 4 to 10

  • WooCommerce shipping zones and rates rebuilt
  • Free shipping threshold made a single source of truth
  • Filter to hide the paid rate once free shipping qualifies
  • Pickup date rule repaired after silent failure
  • Seasonal shipping pause with a dated re-enable
  • Card payments switched from test to live and verified
  • Order confirmation email authentication fixed
  • Events and contact form delivery tested

Search, schema and answer engines, days 3 to 13

  • SEO plugin installed and configured from zero
  • Unique meta description written for every page
  • One H1 per page across the site
  • Organization and Store entity graph on every page
  • Product, Offer and Brand markup on product pages
  • Cafe menu schema and AboutPage markup
  • 17 question and answer pairs written and marked up
  • Answer first opening copy on category archives
  • Yoast sitemap replacing the WordPress default

Migration and hardening, days 10 to 12

  • Redirect map built from sitemap, crawl and search data
  • Host move from SiteGround to Kinsta
  • Edge redirect rules and theme level legacy handling
  • All 199 sitemap URLs verified at 200 after cutover
  • 72 orphaned staging tables dropped after backup
  • Search engine visibility re-enabled, canonicals restored
  • Security pass closing a personal data exposure

Measurement, baseline then day 13

  • Baseline audit of the old site across 6 pages
  • Full page captures of both sites for comparison
  • PageSpeed medians, mobile and desktop
  • Seven signal answer engine audit, before and after
  • Controlled third party tag cost test
  • Synchronised side by side scroll video, 8 pages

Method: Google PageSpeed Insights v5 (Lighthouse), 6 pages, mobile and desktop, median of three runs. My seven signal answer engine audit, 5 pages. Live inspection of headings, metadata and JSON-LD across 10 pages. All 199 sitemap URLs requested individually. Catalogue counts read from the live store. Lab data, point in time, measured three days after launch, so it carries no traffic or ranking claim yet. Measured, not modeled. Metrics current as of day 13.

A tune up can become a rebuild. I tell you which, and why.

Every engagement opens with a diagnostic on a short call: the technical blockers capping your visibility, each with its fix, and an honest read on whether your platform can be tuned or needs rebuilding. Accessible hourly and fixed fee arrangements, so the scope fits the business.

The deliverable. A diagnostic report: the blockers capping your visibility ranked by impact, each with a fix, the answer engine gaps keeping you out of AI results, and a clear recommendation on optimize versus rebuild with the cost of each.

Yours to execute, with me, or on your own.

Want a result like these on your own site?

The most useful hour in this process is the first one, and it happens before any money moves.

Book a diagnosis