Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ yarn-error.log*
# Ignore Draw.io backups.
*.bkp
.playwright-mcp/
scratch/
.wf-clone-tmp/
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,44 @@ Components can be added to global scope, i.e. available in call pages, by adding
src/theme/MDXComponents.js
```

## Analytics

The site uses Google Analytics 4 (`G-8HZFMZV9Z4`), loaded through Google Tag
Manager (`GTM-WS7KMPTS`). Pageviews and outbound clicks are tracked
automatically. Two GTM tags fire custom events when a reader clicks through to
buy the book: `amazon_click` (any `amzn.to` link) and `nostarch_click` (any
`nostarch.com` link). Both are marked as key events in GA4.

### Book click attribution

To see *which* button a buy-click came from — the chapter lead banner, the
chapter footer, the homepage hero, or the menu bar — each book link carries a
`data-book-cta` attribute:

| Value | Where |
|---|---|
| `lead` | Chapter lead banner ([`BookBanner`](src/components/BookBanner)) |
| `finale-cover` / `finale-button` | Chapter footer cover image / buttons ([`BookFooter`](src/components/BookFooter)) |
| `home-hero-button` / `home-hero-cover` / `home-nav` | Homepage hero and nav ([`src/pages/index.tsx`](src/pages/index.tsx)) |
| `menubar` | Docusaurus navbar (toolbar) links, matched by their `header-amazon-link` / `header-nostarch-link` class |
| `sitefooter` | Docusaurus theme footer links, matched by the theme's `.footer` container |

The last two are config-driven ([`docusaurus.config.js`](docusaurus.config.js))
and can't take a `data-book-cta` attribute cleanly, so GTM matches them by class
and container instead — no attribute needed.

GTM reads all this with the `CJS - Book CTA Location` variable, which returns the
clicked link's `data-book-cta`, else `menubar` for the header links, else
`sitefooter` for anything inside the theme footer, and `(unmarked)` otherwise. It
is sent as the `link_location` event parameter and surfaced in GA4 as the
event-scoped custom dimension **Book CTA location**.

Attribution is not retroactive: GA4 only records `link_location` from the point
the tag is live, so newly added CTAs start showing up once this markup deploys.
**When you add a new book link, give it a `data-book-cta` value** — a missing
attribute never breaks tracking (the click still fires), it just reports as
`(unmarked)`.

## Versioning

The version of the site and the code is defined in the [`package.json`](./package.json) file.
Expand Down
4 changes: 2 additions & 2 deletions src/components/BookBanner/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const BookBanner: React.FC = () => {
You're reading the free online edition of Effective Shell. If you're
finding it useful, please consider picking up the print or Kindle edition
from{' '}
<a href="https://nostarch.com/effective-shell" target="_blank" rel="noopener noreferrer">
<a href="https://nostarch.com/effective-shell" data-book-cta="lead" target="_blank" rel="noopener noreferrer">
No Starch Press
</a>{' '}
or{' '}
<a href="https://amzn.to/4ho0F91" target="_blank" rel="noopener noreferrer">
<a href="https://amzn.to/4ho0F91" data-book-cta="lead" target="_blank" rel="noopener noreferrer">
Amazon
</a>{' '}
- or sharing it with someone who'd enjoy it.
Expand Down
4 changes: 3 additions & 1 deletion src/components/BookFooter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import './styles.css';
const BookFooter: React.FC = () => {
return (
<div className="book-footer">
<a href="https://amzn.to/4ho0F91" target="_blank" rel="noopener noreferrer">
<a href="https://amzn.to/4ho0F91" data-book-cta="finale-cover" target="_blank" rel="noopener noreferrer">
<img
src="/images/es-cover-3d.png"
alt="Effective Shell book cover"
Expand All @@ -21,6 +21,7 @@ const BookFooter: React.FC = () => {
<a
className="button button--primary"
href="https://amzn.to/4ho0F91"
data-book-cta="finale-button"
target="_blank"
rel="noopener noreferrer"
>
Expand All @@ -29,6 +30,7 @@ const BookFooter: React.FC = () => {
<a
className="button button--secondary button--outline"
href="https://nostarch.com/effective-shell"
data-book-cta="finale-button"
target="_blank"
rel="noopener noreferrer"
>
Expand Down
8 changes: 5 additions & 3 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,20 @@ function HeroSection() {
</Link>
<Link
className={styles.buttonSecondary}
data-book-cta="home-hero-button"
href="https://amzn.to/4ho0F91">
Amazon
</Link>
<Link
className={styles.buttonSecondary}
data-book-cta="home-hero-button"
href="https://nostarch.com/effective-shell">
No Starch
</Link>
</div>
</div>
<div className={styles.heroImage}>
<a href="https://amzn.to/4ho0F91">
<a href="https://amzn.to/4ho0F91" data-book-cta="home-hero-cover">
<img
className={styles.bookCover}
src="/images/es-cover-3d.png"
Expand Down Expand Up @@ -101,10 +103,10 @@ function Navbar() {
<Link to="/introduction" className={styles.navbarLink}>Read Now</Link>
</div>
<div className={styles.navbarRight}>
<Link href="https://amzn.to/4ho0F91" className={styles.navbarLink}>
<Link href="https://amzn.to/4ho0F91" data-book-cta="home-nav" className={styles.navbarLink}>
Amazon
</Link>
<Link href="https://nostarch.com/effective-shell" className={styles.navbarLink}>
<Link href="https://nostarch.com/effective-shell" data-book-cta="home-nav" className={styles.navbarLink}>
No Starch
</Link>
<Link href="https://github.com/dwmkerr/effective-shell" className={styles.navbarLink}>
Expand Down
Loading