Part 3 — Custom Code · DesmondGriffiths.com
DesmondGriffiths.com · Implementation Task List

Part 3 of 6 — Custom Code

Every code block that must be installed: Google Fonts, CSS overrides, JSON-LD schema, Google Analytics, page-specific JavaScript, and validation. All copy-paste ready.

0Done
0Total
0%Complete
0Remaining
Location

Header Page Scripts — Settings → Site Details → Header Page Scripts

How this field works: Code pasted here is injected into the <head> of every website page. Requires <style> and <script> wrapper tags. This field does NOT apply to Kajabi checkout/offer pages — those need separate injection. Install all blocks below in a single paste, in order.
Block 1 — Google Fonts (Cormorant Garamond + Jost)
  • Paste the Google Fonts preconnect + link tags into Header Page ScriptsMust be the first block. The preconnect tags reduce font load time by ~200ms.
    Critical
Copy and paste into Header Page Scripts
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400;1,500;1,600&family=Jost:wght@200;300;400;500;600&display=swap" rel="stylesheet">
Block 2 — CSS Font Override (applies both fonts site-wide)
  • Paste the CSS override block — this applies Cormorant Garamond to all headings and Jost to all body/nav/buttons!important is required. Kajabi emits inline font-family styles that override external CSS without it. Do not remove !important.
    Critical
  • After pasting, load the homepage and inspect an H1 element in browser developer tools → computed font-family must read "Cormorant Garamond"
    Validate
  • Inspect a nav link → computed font-family must read "Jost"
    Validate
CSS Override Block — paste after Google Fonts link tag
<style>
/* ── DesmondGriffiths.com — Custom Font System ── */

/* CSS Variables */
:root {
  --font-heading: 'Cormorant Garamond', Georgia, serif !important;
  --font-body: 'Jost', 'Helvetica Neue', Arial, sans-serif !important;
  --color-bg: #FAF7F2;
  --color-gold: #B8945A;
  --color-ink: #0F0E0C;
  --color-body: #5A5650;
  --color-slate: #1E2029;
  --color-mist: #E8E3DA;
}

/* Headings — Cormorant Garamond */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
[class*="heading"], [class*="title"],
.site-header__title, .hero__title {
  font-family: 'Cormorant Garamond', Georgia, serif !important;
  letter-spacing: 0.01em;
}
h1, .h1 { font-weight: 300 !important; line-height: 1.05 !important; }
h2, .h2 { font-weight: 300 !important; line-height: 1.1 !important; }
h3, .h3 { font-weight: 400 !important; }
h4, h5, h6 { font-weight: 400 !important; }
h1 em, h2 em, h3 em, h1 i, h2 i, h3 i { font-style: italic !important; }

/* Body, nav, buttons, forms — Jost */
body, p, span, li, a, label, div,
input, textarea, select, button,
.btn, .form-btn, .button,
nav, .nav, .navbar, .menu, .menu-item,
.site-nav, .site-header {
  font-family: 'Jost', 'Helvetica Neue', Arial, sans-serif !important;
  font-weight: 300 !important;
}
nav a, .menu-item a, .navbar a,
.site-nav a, .site-header a {
  font-weight: 500 !important;
  letter-spacing: 0.06em;
}
.btn, .form-btn, button, [type="submit"],
.btn--primary, .btn--secondary {
  font-weight: 500 !important;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
strong, b { font-weight: 600 !important; }
small, .small, .caption, .eyebrow { font-weight: 300 !important; }
</style>
Block 3 — Person JSON-LD Schema (establishes Des as named entity in Google and AI systems)
  • Paste Person JSON-LD schema. Before pasting, update: replace [YOUR-PORTRAIT-URL] with the actual uploaded portrait URL, replace [YOUR-LINKEDIN-HANDLE] with Des's LinkedIn handle
    Critical
  • Validate schema at search.google.com/test/rich-results after installation
    Validate
Person JSON-LD — update portrait URL and LinkedIn handle before pasting
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": ["Person", "ProfessionalService"],
  "@id": "https://www.desmondgriffiths.com/#des",
  "name": "Desmond Griffiths",
  "jobTitle": "Executive Coach, Consultant, and Integration Practitioner",
  "description": "Guide, coach, builder, healer, and companion for those navigating complexity in life, leadership, and legacy. ICF-grounded practice. Born in South Africa. Based in San Diego, California. Serving globally.",
  "url": "https://www.desmondgriffiths.com",
  "image": "https://www.desmondgriffiths.com/[YOUR-PORTRAIT-URL]",
  "sameAs": [
    "https://www.linkedin.com/in/[YOUR-LINKEDIN-HANDLE]",
    "https://www.desmondgriffiths.coach"
  ],
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "San Diego",
    "addressRegion": "CA",
    "addressCountry": "US"
  },
  "knowsAbout": [
    "Executive Coaching",
    "Life Coaching",
    "Leadership Development",
    "Integration Coaching",
    "Business Consulting",
    "Privacy and Data Governance",
    "Organizational Transformation",
    "ICF Ethics"
  ],
  "hasCredential": {
    "@type": "EducationalOccupationalCredential",
    "credentialCategory": "Professional Coaching",
    "recognizedBy": {
      "@type": "Organization",
      "name": "International Coaching Federation",
      "url": "https://coachingfederation.org"
    }
  },
  "areaServed": {
    "@type": "Place",
    "name": "Global"
  }
}
</script>
Block 4 — FAQPage JSON-LD Schema (AI search citability for FAQ content)
  • Paste the starter FAQPage schema now with these 3 high-priority questions. Expand to all 30 FAQ questions in Phase 2 after faq.html is live.
    Critical
  • Validate at search.google.com/test/rich-results — confirm FAQPage type is recognized
    Validate
FAQPage JSON-LD — starter set (expand to all 30 in Phase 2)
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What is the difference between coaching and therapy?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Therapy often works on the past: uncovering patterns and healing wounds. Coaching works on the present in service of the future. It assumes you are already capable and resourceful, and asks: what is between you and what you actually want? Coaching with Desmond Griffiths is future-focused, client-led, and designed to support clarity, growth, and aligned action."
      }
    },
    {
      "@type": "Question",
      "name": "Is coaching worth the financial investment?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "An International Coaching Federation study by PricewaterhouseCoopers found that organizational coaching yields an average return of nearly 700%. Beyond financial return, coaching builds stronger relationships, greater self-belief, sharper decision-making, and a more fulfilling, sustainable way of living and leading. The investment is designed to keep paying dividends long after the engagement ends."
      }
    },
    {
      "@type": "Question",
      "name": "Who is Desmond Griffiths as a coach?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Desmond Griffiths is an executive coach, consultant, and integration practitioner based in San Diego, California. Born in South Africa and shaped by experience across six continents, he works with leaders, creatives, and conscious professionals navigating transitions in life, leadership, and legacy. His practice is ICF-grounded and draws on ancient wisdom, emerging science, and practical guidance for the age of intelligence."
      }
    },
    {
      "@type": "Question",
      "name": "Will I feel pressured to sign up during the discovery call?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. The discovery call is a genuine conversation for both parties. It ends when the conversation has run its natural course. Whatever you decide afterward is respected without follow-up pressure. Pricing and package details are published openly on the Store page — nothing is hidden behind a call."
      }
    },
    {
      "@type": "Question",
      "name": "What happens between coaching sessions?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Every engagement includes support between sessions. The specific form — message access, check-in touchpoints, voice note access — is scoped in the initial agreement based on what you actually need. Life does not wait for the next scheduled session, and neither does the support."
      }
    }
  ]
}
</script>
Block 5 — Google Analytics 4
  • Replace G-XXXXXXXXXX with your actual GA4 Measurement ID from analytics.google.com → Admin → Data Streams → Web
    Critical
  • After pasting, visit the live site and check GA4 Realtime report → confirm session appears within 30 seconds
    Validate
GA4 — replace G-XXXXXXXXXX with your Measurement ID
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');
</script>
Block 6 — Google Search Console Verification
  • Get the HTML meta tag from Search Console → Add Property → HTML tag method. Paste it here.Format: <meta name="google-site-verification" content="YOUR_CODE_HERE" />
    Critical
  • After pasting, return to Search Console and click Verify. Confirmation appears within seconds if tag is live.
    Validate
Page CSS

Page-Specific Custom CSS

Website → Pages → Customize → Page Settings → CSS
Where to paste: Per-page CSS goes in the page editor sidebar → Settings → Custom Code → CSS field. Do NOT include <style> tags in this field — the field auto-wraps your code. Only paste the raw CSS rules.
Consult Page — Subtle Grid-Line Hero Background
  • Add grid-line texture to the Consult page hero section only
    Code
Paste in Consult page CSS field (no style tags)
.hero-grid-lines, .section--hero {
  background-image:
    linear-gradient(rgba(245,240,232,0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(245,240,232,0.03) 1px, transparent 1px);
  background-size: 48px 48px;
}
Integrate Page — Concentric Ring Hero Accent
  • Add concentric rings to Integrate page hero — hide on mobile
    Code
Paste in Integrate page CSS field (no style tags)
.hero-rings {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none; z-index: 0;
}
.hero-rings .ring {
  position: absolute; border-radius: 50%;
  border: 1px solid rgba(184,148,90,0.07);
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}
.ring-1 { width: 300px; height: 300px; }
.ring-2 { width: 500px; height: 500px; }
.ring-3 { width: 700px; height: 700px; }
.ring-4 { width: 900px; height: 900px; opacity: 0.5; }
@media (max-width: 768px) {
  .hero-rings { display: none; }
}
Nav — Gold Underline on Connect CTA Link
  • Style the "Connect" nav link distinctively — gold color + border-bottom to signal it's the CTAAdd to Header Page Scripts CSS block, not per-page. This applies site-wide.
    Code
Add inside the <style> block in Header Page Scripts
/* Connect CTA in nav */
.site-nav a[href*="contact"],
.site-nav a[href*="connect"],
.nav-cta {
  color: #B8945A !important;
  border-bottom: 1px solid #B8945A !important;
  padding-bottom: 1px;
  opacity: 1 !important;
}
JavaScript

Page-Specific JavaScript

Installed via Custom Code Block on each page
Where to paste: Add a Custom Code Block to the page in the Kajabi editor → paste the <script> tag. Or use the page-level Header Page Script if available. Reference the exact script from the corresponding HTML prototype file.
Scroll Reveal Animation — All Pages
  • Add scroll reveal script to every page — makes sections animate up on scroll. Reference: any prototype HTML file <script> block → "Scroll reveal" comment.Key: threshold:0 and getBoundingClientRect() check ensures elements already in viewport reveal on load. This fixes the "missing content" bug when opening files locally.
    Code
Scroll Reveal — add to every page via Custom Code Block
<script>
document.addEventListener('DOMContentLoaded', function() {
  const reveals = document.querySelectorAll('.reveal');
  const io = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        e.target.classList.add('visible');
        io.unobserve(e.target);
      }
    });
  }, { threshold: 0 });
  reveals.forEach(el => {
    const rect = el.getBoundingClientRect();
    if (rect.top < window.innerHeight) {
      el.classList.add('visible');
    } else {
      io.observe(el);
    }
  });
});
</script>
FAQ Accordion — FAQ Page Only
  • Add FAQ accordion + sticky TOC tracking script to the FAQ page only. Reference: faq.html full <script> block.
    Code
  • Verify: clicking a question expands it and collapses any previously open question
    Validate
  • Verify: scrolling through FAQ categories updates the active link in the sticky left TOC
    Validate
  • Verify: first question in each category opens by default on page load
    Validate
Blog Category Filter — Blog Page Only
  • Add blog category filter script to Blog index page. Reference: blog.html <script> block → filterArticles function.
    Code
  • Verify: clicking a category button fades non-matching articles to 30% opacity and disables pointer events
    Validate
  • Verify: clicking "All" restores full opacity on all articles
    Validate
  • Confirm article cards have the correct data-category attribute matching the filter button valuesdata-category values: "coach" | "consult" | "integrate" | "approach" | "personal"
    Code
Validate

Code Validation Checklist

Run after all code is installed
  • Rich Results Test: search.google.com/test/rich-results → test homepage URL → confirm Person and FAQPage types are detected with no errors
    Validate
  • Schema.org Validator: validator.schema.org → paste homepage URL → confirm no warnings on Person schema
    Validate
  • Browser DevTools: open Console tab on live site → confirm zero JavaScript errors on page load
    Validate
  • Browser DevTools: open Network tab → filter by "fonts.gstatic.com" → confirm Cormorant Garamond and Jost are loading with status 200
    Validate
  • GA4 Realtime: visit live site → check GA4 Realtime report → confirm session appears within 60 seconds
    Validate
  • HTTPS: confirm padlock icon in all major browsers. DevTools → Console → check for Mixed Content warnings.
    Critical
  • PageSpeed Insights: pagespeed.web.dev → test homepage → target 80+ on mobile. If font loading causes LCP delay, fonts are already preconnected — further optimization may require font subsetting.
    Validate
  • If apostrophes in 'Cormorant Garamond' or 'Jost' are stripped by the Kajabi editor on save, re-add them — Kajabi occasionally strips quote marks from CSS font declarationsKnown Kajabi behavior. Check fonts after every Style Guide or code save.
    Critical