Squarely website -> Amazon funnel audit (2026-05-13)
Summary
Live site is https://squarelypuzzle.com/ (Astro v6.1.9 on Cloudflare Pages, repo ~/Projects/squarely-web). The relaunch is materially shipped: 3 routes (/, /play, /tips), 3 Amazon book CTAs, a working web demo, a working waitlist API with welcome email, and Cloudflare Web Analytics wired up. There are 3 BLOCKER bugs that materially hurt funnel conversion right now: (a) og:url is hardcoded to http://localhost:4321/ so all social shares are mis-attributed; (b) og:squarely.png does not exist (SPA fallback serves HTML, so LinkedIn/Twitter/iMessage previews have no image); (c) footer + /play "Get notified" anchors point to non-existent IDs (#app, #email-capture) on every non-home page, dead-ending users. Amazon-funnel verdict: partial-leverage - the path home -> #books -> Amazon works in 2 clicks and the links are clean, but zero UTM tagging and zero Amazon Associates tag means we cannot measure or monetize the inbound at all. Strategy-aligned read: per STRATEGY.md the website is explicitly NOT the engine (Amazon Search/Browse is), so polish it enough to not embarrass us and stop dead-ending users, but do not invest in deep funnel work until KDP listing + Amazon Ads instrumentation is in flight.
Live state (2026-05-13 audit)
- URL:
https://squarelypuzzle.com/ - Deploy target: Cloudflare Pages, project
squarely-web, branchmain(via.github/workflows/deploy.yml) - Framework: Astro v6.1.9 + Tailwind v4
- Last main commit:
7161665("HowItWorks: align rule descriptions with book + tighten beauty paragraph"), May 2 2026 - Routes:
/- home (Hero, HowItWorks, WebGame teaser, Books, Testimonials, AboutJohn, WarmStory, EmailCapture/waitlist, Footer)/play- 12-puzzle browser demo, 4 difficulty tiers/tips- 4 HyperFrames-rendered tutorial videos
- API:
/api/waitlistPOST endpoint - tested live, returns{ok:true, welcomeSent:true}, setssq_waitlistedcookie. Welcome email links tohttps://www.amazon.com/dp/B0CD91ZLCY(Book 1, no UTM) - Analytics: Cloudflare Web Analytics beacon present in
Base.astrohead, BUT see Polishing item P3 - beacon is being CORS-blocked in production - Screenshots:
screenshots-2026-05-13/directory has desktop + mobile captures of all 3 routes
Polishing punchlist
BLOCKER (ship this cycle)
- B1 -
og:urlis hardcoded to localhost.src/layouts/Base.astro:25setscanonicalUrl = Astro.urlwhich at SSG build time resolves tohttp://localhost:4321/. Every Open Graph URL, every canonical link, every Twitter card URL points to localhost. Verified live:og:urlcontent ishttp://localhost:4321/. Fix: hardcodeconst SITE = 'https://squarelypuzzle.com';and compose URLs fromAstro.url.pathname. Or setsiteinastro.config.mjsand useAstro.site. - B2 -
og:squarely.pngdoes not exist. Live URL returns 200 but content-type istext/html(SPA fallback serves the home page HTML). Verified:curl -s https://squarelypuzzle.com/og-squarely.pngreturns<!DOCTYPE html>.... Every social share will show no preview image.public/directory hasapp/,books/,doodles/,favicon.ico,favicon.svg,logo/,people/,videos/but noog-squarely.png. Fix: generate and add a 1200x630 OG card. - B3 - Dead
#appanchor in every footer.Footer.astro:25links to#appbut no element on any page has that ID. Verified:document.getElementById('app')returns null on/,/play,/tips. Fix: either addid="app"to the iPhone-mockup half ofEmailCapture.astro, or change the footer link to#get-waitlist. - B4 - Dead
#email-captureanchor on /play./play"Get notified" CTA links to/#email-capturebut the actual home section ID is#get-waitlist(and the title element ID is#email-capture-title). User clicks "Get notified" -> lands at top of home with no scroll. Fix: change /play link to/#get-waitlist. - B5 - Footer anchors are relative on /play and /tips. Footer "How it works / Books / About John" links use
href="#how-it-works"which resolves to/play/#how-it-workson the play page, and these IDs do not exist there. Footer nav is non-functional from /play and /tips. Fix: use absolute/#how-it-works,/#books,/#aboutinFooter.astro.
SHOULD (high-leverage but not blocking)
- S1 - Zero UTM tagging on any Amazon link. Three "Buy on Amazon" CTAs in
Books.astroand one inTestimonials.astropoint to barehttps://www.amazon.com/dp/B0CD91ZLCY|B0DJ5SZRYN|B0FYNPYM1Z. Without?tag=...and a source param, we cannot tell from KDP reports whether any inbound came from the website. Fix: add Associates tag +?ref=squarelypuzzle.com&campaign=home_books_ctastyle param (Amazon strips most buttag=is honored). Also tag the welcome-email link infunctions/api/waitlist.ts:65. - S2 - No Amazon Associates tag. Beyond UTM, we are leaving the Associates affiliate cut on the table (~4-10% on each book sale via own-site referral). Founder owns the books, so the Associates fee is recoverable revenue we are not collecting. Fix: sign up for Amazon Associates if not already; append
?tag=YOUR_ASSOCIATES_TAGto every Amazon link. - S3 - Cloudflare Web Analytics is CORS-blocked. Live console errors:
Access to XMLHttpRequest at 'https://cloudflareinsights.com/cdn-cgi/rum' from origin 'https://squarelypuzzle.com' has been blocked by CORS policy. Analytics are NOT firing on the live site. Verify CF token + that the Web Analytics property is configured for the right origin in the dashboard. Until fixed, we have no traffic data and cannot answer "is the website driving Amazon clicks." - S4 - No outbound-click tracking on Amazon CTAs. Even with CF Analytics fixed, by default it tracks pageviews not outbound clicks. Add a
data-cf-clickstyle event or wire a smallgtag/plausible/CF Custom Eventon each Amazon CTA. Without this, we cannot answer the founder's actual question. - S5 -
/playhas no<h1>. Verified zero<h1>elements on/play. Hurts SEO and a11y. The "Squarely" wordmark next to the logo is a logo, not a heading. Fix: add visually-hidden or visible<h1>Play Squarely</h1>. - S6 -
/tipshas no Amazon CTAs. A user lands on /tips (via search for "squarely tips" or sharing), watches 4 videos, and is offered only/playor/#books. No direct Amazon link. Fix: add a "Print editions" book-tile CTA at the bottom of /tips that links directly to Amazon Book 1 (with UTM), so visitors who prefer paper can convert without an extra hop. - S7 - Hero "Get the books" CTA is a same-page anchor. Users scrolling fast from a paid ad land, see "Get the books", click, scroll to Books section, then must click again to reach Amazon. That is 3 clicks not 2. Fix: consider making the Hero primary CTA link directly to Book 1's Amazon page (with UTM); keep the "How it works" secondary CTA. Trade-off: same-page anchor preserves brand-pitch surface area; direct link wins on funnel speed.
- S8 -
/tipsvideos have noposterattribute. Four autoplay-muted videos without posters. Creates Cumulative Layout Shift on first load and a blank frame before video data arrives. Fix: add a poster image per video (extract first frame to.webp). - S9 -
/tipsvideos lackaria-labelandplaysinline. Mobile Safari may not autoplay withoutplaysinline. Verified:videosarray showsautoplay:true, muted:truebut noplaysinlinechecked in audit. Fix: addplaysinlineattribute. - S10 - No
sitemap.xml. Returns the home HTML (SPA fallback). Hurts crawlability. Fix: add@astrojs/sitemapintegration or hand-roll a staticpublic/sitemap.xml. - S11 - No
robots.txtallow/sitemap line specific to Squarely. Current/robots.txtserves Cloudflare's default content-signals robots file. Should also reference the sitemap once it exists.
NICE-TO-HAVE
- N1 - Image
alton Amazon-CDN book covers could be richer. Currentlyalt="Squarely: Book 1 cover". Could include keywords:"Squarely: Book 1 - 100 logic puzzles by John H. Wilson - paperback cover". Marginal SEO + a11y win. - N2 - Hero copy "Two rules" is great; everywhere else is verbose. Some sections (WarmStory, AboutJohn) have multi-paragraph blocks. Mobile users will bounce. Consider a "Show more" pattern or tighter copy on mobile. Defer to founder taste.
- N3 - Testimonials show 9 reviews but no link to all reviews. Trust signal could compound by linking "See more reviews on Amazon" deep-linked to the reviews tab of Book 1. Currently only the inline Amazon nudge link exists.
- N4 - No schema.org markup. Adding
Product/BookJSON-LD on each book card would help Google show rich results in search. Mid-effort, mid-payoff. - N5 -
/play"Coming soon" iOS card has no concrete date. "Daily puzzles, leaderboards, streaks. Get notified." is fine, but if a TestFlight date is known it would convert better. - **N6 - WebGame teaser on home links to
/playbut says "Twelve sample puzzles across four difficulty tiers" while/playshows three sample puzzles per tier (12 total, four tiers). Copy is technically correct; the off-by-one feel might benefit from re-phrasing as "Twelve sample puzzles, four tiers".
Amazon-funnel state
What works
- Three "Buy on Amazon" CTAs in the Books section, each going to the correct ASIN dp page (
B0CD91ZLCY,B0DJ5SZRYN,B0FYNPYM1Z). All open in new tab with properrel="noopener noreferrer". - An additional Amazon nudge link in the Testimonials section (also to Book 1).
- The waitlist welcome email surfaces a fourth Amazon link to Book 1 as a "while you wait" nudge - good move per
functions/api/waitlist.ts:325. - Real Amazon CDN cover artwork is being used (not stylized mockups), which builds trust.
What does not work
- Zero UTM tagging on any Amazon link anywhere on the site or in transactional email. We cannot attribute KDP unit sales to the website at all.
- Zero Amazon Associates tag. Affiliate revenue is being left on the table on every conversion that does happen.
- Cloudflare Web Analytics is CORS-blocked in production, so we have no traffic data either.
- No outbound-click event tracking. Even if analytics worked, page-views alone do not answer "is the website driving Amazon clicks."
Primary CTAs and destinations
| Surface | CTA text | Destination | UTM? | Direct to Amazon? |
|---|---|---|---|---|
| Home hero | "Get the books" | /#books (in-page anchor) |
n/a | No (2 clicks needed) |
| Home hero | "How it works" | /#how-it-works |
n/a | No |
| Home WebGame | "Start playing" | /play |
n/a | No |
| Home Books x3 | "Buy on Amazon" | amazon.com/dp/ASIN |
No | Yes (1 click from Books section) |
| Home Testimonials | "Amazon" | amazon.com/dp/B0CD91ZLCY |
No | Yes |
| Home EmailCapture | "play it right now" | /play |
n/a | No |
| /play | "Get the books" | /#books |
n/a | No (2 clicks) |
| /play | "Get notified" | /#email-capture (DEAD ANCHOR) |
n/a | No |
| /tips x4 | "Try it on the play page" | /play |
n/a | No |
| /tips | "Get the books" | /#books |
n/a | No (2 clicks) |
| Welcome email | "The puzzle books are on Amazon" | amazon.com/dp/B0CD91ZLCY |
No | Yes |
Conversion-friction count
Clicks from landing on home to opening Amazon Book 1 listing:
- Best case: 1 click (scroll to Books section, click "Buy on Amazon" - but the user has to scroll first; the Hero "Get the books" CTA also jumps them there, so 1 click from the visible Hero CTA + 1 click on Amazon button = 2 clicks).
- Realistic: 2 clicks from any landing surface (home/play/tips), because no top-of-page CTA points directly to Amazon.
- Welcome email: 1 click (direct Amazon link).
For comparison, a "buy now" direct link in the Hero would be 1 click from home. The trade is fewer eyes on the brand pitch.
Recommendations
Ship this cycle (~3-4 hours total)
The BLOCKER set is small and mechanical. Strong "do it now" recommendation:
- Fix
og:urlto be the production URL (Base.astro) - 5 min - Generate and ship
og-squarely.png(1200x630, can be Hero board screenshot with wordmark overlay) - 30 min - Fix the dead
#appand#email-captureanchors - either change the IDs in components or change the links in Footer/play - 10 min - Make footer anchors absolute (
/#booksnot#books) - 5 min - Add UTM + Associates tag to all 5 Amazon links (3 in Books, 1 in Testimonials, 1 in welcome email) - 20 min. Use a single helper:
amazonUrl(asin, source)that returnshttps://www.amazon.com/dp/${asin}?tag=${ASSOC_TAG}&linkCode=...&campaign=${source}. - Debug Cloudflare Web Analytics CORS error - probably a token/origin misconfiguration in the CF dashboard. 15 min.
- Add outbound-click tracking to Amazon CTAs (custom event via CF Web Analytics or Plausible) - 30 min.
- Add
<h1>Play Squarely</h1>to /play - 5 min.
After these eight, we have a clean enough funnel to actually measure whether the website is driving Amazon clicks.
Founder decision needed
- Hero CTA: in-page anchor vs direct Amazon link. Tightens the funnel from 2 clicks to 1, at the cost of less brand-pitch exposure. The S7 punchlist item. Recommend leaving as anchor since the site is brand/discovery per STRATEGY, but flag for explicit founder call.
- Amazon Associates signup. Requires founder action (TIN/payout setup). Material recoverable revenue (~4-10% of book sale).
- Generate
og-squarely.pngstyle. Could be a screenshot of the Hero board or a custom illustrated card. Touch the founder doodle aesthetic? Defer to founder. - Add Book + Product schema.org JSON-LD. Mid-effort, helps Google rich results. Worth doing only if we are committing to the website as a discovery surface (which STRATEGY says we are not).
Park for now
- Deeper SEO investment (long-tail content marketing, blog, etc.) - per STRATEGY, Amazon Search is the engine, not the website. Do not invest here until KDP listing + Amazon Ads are instrumented and tuned.
- A/B testing Hero CTA copy - sample size will be tiny (current traffic is unknown but small).
- Newsletter / content cadence - the waitlist captures emails for product launches, not for an editorial newsletter. Leave as-is.
- Adding paid traffic to the site - useless until UTM + outbound tracking exists.
- Building separate landing pages per book - premature; Amazon listings already serve this purpose with better intent-match.
Continue-vs-park read on website-as-Amazon-funnel
Verdict: partial-leverage. Polish the obvious leaks, then park.
Per STRATEGY.md, the explicit thesis is that the website is NOT the engine - Amazon Search/Browse is. The website's job is brand/discovery support: a place where someone who heard about Squarely (via personal-network push, future iOS app shares, podcast mention) can land, get the story, and decide to buy on Amazon. It is a funnel exit, not a funnel entry.
At current state, with BLOCKERS present, the website is worse than a placeholder because broken anchors and missing OG images actively dead-end users who otherwise would have converted. After the 3-4 hour BLOCKER + SHOULD fix pass, the website becomes a clean exit to Amazon: 1-2 clicks to a tracked, attributed Amazon link from any landing page.
For the website to be a load-bearing funnel, three things would have to be true:
- Material organic traffic exists (currently unknown - analytics are CORS-blocked, but baseline assumption is tens of visits/month, not hundreds)
- Outbound-click data shows >20% click-through to Amazon (industry baseline for direct-product landing pages)
- Amazon attribution data shows website-attributed conversions converting at competitive rates
None of these can be verified today. Step 1 of verifying them is fixing the BLOCKER+SHOULD list. After that, give it 30 days of fixed analytics and re-read.
The honest read for the founder: the website is brand/discovery. It is worth keeping clean (the 3-4 hours of polish) because it is a free funnel exit and an SEO surface that John H. Wilson can hand to puzzle reviewers/podcasts. It is NOT worth investing in deep funnel work, content marketing, or A/B testing - that energy goes to KDP listing optimization, Amazon Ads instrumentation (the founder-picked critical component per STRATEGY.md), and shipping the iOS app.