Death Readiness Quiz - Complete Implementation Guide

Overview

This guide provides step-by-step instructions to add a fully functional quiz/scorecard system to your Eleventy website at talkwithdeath.com.


Table of Contents

  1. File Structure
  2. Backend Options
  3. Step-by-Step Implementation
  4. Testing & Deployment
  5. Email Integration
  6. Analytics & Tracking

File Structure

Your Eleventy site will need these new files:

your-site/
├── _data/
│   └── assessmentQuestions.json          # Quiz data (CREATED ✓)
├── quiz/
│   ├── index.njk                    # Landing page (CREATED ✓)
│   ├── assessment.njk               # Main quiz page (CREATED ✓)
│   └── results.njk                  # Results display (TO CREATE)
├── js/
│   └── assessment-engine.js               # Quiz logic (TO CREATE - see below)
├── netlify/
│   └── functions/
│       ├── submit-assessment.js           # Backend submission (TO CREATE)
│       └── send-email.js            # Email handler (TO CREATE)
└── css/
    └── (styles already in assessment.njk)

Backend Options

RECOMMENDED: Netlify Forms + Functions

Pros:

Setup:

  1. Already using Netlify for hosting
  2. Add functions directory
  3. Configure environment variables

package.json additions:

{
  "dependencies": {
    "@sendgrid/mail": "^7.7.0"
  }
}

Alternative 1: Formspree

Alternative 2: Google Sheets + Apps Script

Alternative 3: Airtable


Implementation Steps

Step 1: Add Quiz Data File

File: _data/assessmentQuestions.json
Status: ✓ CREATED (already provided above)

Step 2: Create Quiz Landing Page

File: quiz/index.njk
Status: ✓ CREATED (already provided above)

Step 3: Create Quiz Assessment Page

File: quiz/assessment.njk
Status: ✓ CREATED (already provided above)

Step 4: Create Complete assessment-engine.js

File: js/assessment-engine.js

You'll need to download the complete JavaScript file. Due to length, I'll provide it as a separate file that combines:

Key features:

Step 5: Create Results Page

File: quiz/results.njk

---
layout: base.njk
title: Your Results
description: Your Death Readiness Assessment Results
---

<div class="results-page">
  <div class="container">
    <div id="resultsContent">
      <!-- Populated by JavaScript -->
    </div>
  </div>
</div>

<script src="/js/assessment-results.js"></script>

<style>
.results-page {
  padding: var(--space-xxl) 0;
  background: var(--color-background);
}

.results-hero {
  background: var(--color-primary);
  color: var(--color-white);
  padding: var(--space-xl);
  border-radius: 8px;
  text-align: center;
  margin-bottom: var(--space-xl);
}

.score-display {
  font-size: 4rem;
  font-weight: 700;
  color: var(--color-accent);
  margin: var(--space-md) 0;
}

.tier-badge {
  display: inline-block;
  background: var(--color-accent);
  color: var(--color-primary);
  padding: var(--space-sm) var(--space-lg);
  border-radius: 50px;
  font-weight: 600;
  font-size: 1.2rem;
  margin-bottom: var(--space-md);
}

.results-message {
  background: var(--color-white);
  padding: var(--space-xl);
  border-radius: 8px;
  margin-bottom: var(--space-lg);
}

.recommendations {
  background: var(--color-white);
  padding: var(--space-xl);
  border-radius: 8px;
}

.recommendations ul {
  list-style: none;
  padding: 0;
}

.recommendations li {
  padding: var(--space-md);
  margin-bottom: var(--space-sm);
  background: var(--color-background);
  border-radius: 4px;
  border-left: 4px solid var(--color-accent);
}

.cinderella-offer {
  background: linear-gradient(135deg, var(--color-accent), #FFE666);
  color: var(--color-primary);
  padding: var(--space-xxl);
  border-radius: 8px;
  text-align: center;
  margin: var(--space-xl) 0;
  border: 3px solid var(--color-primary);
}

.cinderella-offer h2 {
  color: var(--color-primary);
}

.category-breakdown {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: var(--space-md);
  margin: var(--space-lg) 0;
}

.category-card {
  background: var(--color-white);
  padding: var(--space-md);
  border-radius: 6px;
  border-top: 4px solid var(--color-accent);
}
</style>

Step 6: Create Results JavaScript

File: js/assessment-results.js

class QuizResults {
  constructor() {
    this.resultsData = this.loadResults();
    if (this.resultsData) {
      this.render();
    } else {
      window.location.href = '/quiz/';
    }
  }

  loadResults() {
    const data = sessionStorage.getItem('quizResults');
    return data ? JSON.parse(data) : null;
  }

  render() {
    const container = document.getElementById('resultsContent');
    
    // Load quiz data for tier information
    const tier = this.getTierData(this.resultsData.tier);
    const isCinderella = this.resultsData.isCinderellaClient;
    
    let html = `
      <div class="results-hero">
        <div class="tier-badge">${tier.title}</div>
        <div class="score-display">${this.resultsData.score}/100</div>
        <p class="lead">Your Death Readiness Score</p>
      </div>

      <div class="results-message">
        <h2>What This Means</h2>
        <p class="lead">${tier.message}</p>
      </div>
    `;

    // Cinderella client special offer
    if (isCinderella) {
      html += `
        <div class="cinderella-offer">
          <h2>🌟 Special Invitation for You 🌟</h2>
          <p class="emphasis">Based on your readiness and clarity, you're an ideal candidate for our signature 'Death Integration' 12-week program.</p>
          <p>As someone who completes this assessment with your level of commitment, you receive priority booking and 20% off the program fee.</p>
          <p><strong>Only 3 spots available this quarter.</strong></p>
          <a href="${tier.cta.url}" class="btn-primary" style="margin-top: var(--space-md);">
            Claim Your Priority Spot
          </a>
        </div>
      `;
    }

    html += `
      <div class="recommendations">
        <h2>Your Next Steps</h2>
        <ul>
          ${tier.recommendations.map(rec => `<li>${rec}</li>`).join('')}
        </ul>
        <div class="cta-section">
          <a href="${tier.cta.url}" class="btn-primary">
            ${tier.cta.text}
          </a>
          ${tier.cta.subtitle ? `<p><small>${tier.cta.subtitle}</small></p>` : ''}
        </div>
      </div>
    `;

    container.innerHTML = html;

    // Track conversion
    this.trackResults();
  }

  getTierData(tierName) {
    // In production, load from assessmentQuestions.json
    // For now, return based on tier name
    const tiers = {
      'death-doula-ready': {
        title: 'Death Doula Ready',
        message: 'You\'re remarkably open to exploring death...',
        // ... full tier data
      }
      // ... other tiers
    };
    return tiers[tierName];
  }

  trackResults() {
    // Google Analytics tracking
    if (window.gtag) {
      gtag('event', 'quiz_completed', {
        score: this.resultsData.score,
        tier: this.resultsData.tier,
        is_cinderella: this.resultsData.isCinderellaClient
      });
    }
  }
}

document.addEventListener('DOMContentLoaded', () => {
  new QuizResults();
});

Step 7: Create Netlify Function

File: netlify/functions/submit-assessment.js

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

exports.handler = async (event) => {
  if (event.httpMethod !== 'POST') {
    return { statusCode: 405, body: 'Method Not Allowed' };
  }

  try {
    const data = JSON.parse(event.body);
    
    // Send email to admin
    await sgMail.send({
      to: process.env.ADMIN_EMAIL,
      from: process.env.FROM_EMAIL,
      subject: `New Quiz Submission - ${data.tier.toUpperCase()}${data.isCinderellaClient ? ' 🌟 PRIORITY' : ''}`,
      html: formatEmailHTML(data)
    });

    // Send email to user (if they provided email - you'd need to add email capture)
    
    return {
      statusCode: 200,
      body: JSON.stringify({ success: true })
    };
  } catch (error) {
    console.error(error);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Submission failed' })
    };
  }
};

function formatEmailHTML(data) {
  return `
    <h2>New Quiz Submission</h2>
    <p><strong>Score:</strong> ${data.score}/100</p>
    <p><strong>Tier:</strong> ${data.tier}</p>
    <p><strong>Cinderella Client:</strong> ${data.isCinderellaClient ? 'YES ⭐' : 'No'}</p>
    
    <h3>Qualifying Questions:</h3>
    <ul>
      <li>Urgency: ${data.qualifiers.urgency?.value}</li>
      <li>Investment: ${data.qualifiers.investment?.value}</li>
      <li>Decision Maker: ${data.qualifiers['decision-maker']?.value}</li>
      <li>Support Type: ${data.qualifiers['support-type']?.value}</li>
    </ul>

    <h3>All Answers:</h3>
    <pre>${JSON.stringify(data.answers, null, 2)}</pre>
    
    <p><small>Submitted: ${data.timestamp}</small></p>
  `;
}

Environment Variables

Add to Netlify dashboard (Settings > Environment Variables):

SENDGRID_API_KEY=your_sendgrid_api_key
ADMIN_EMAIL=your-email@example.com
FROM_EMAIL=noreply@talkwithdeath.com

Testing Checklist

Local Testing

Backend Testing

Mobile Testing


Deployment Steps

  1. Commit all files to repository
  2. Push to GitHub/GitLab
  3. Netlify auto-deploys
  4. Set environment variables in Netlify
  5. Test on live site
  6. Set up email templates
  7. Create follow-up sequences

Alternative: Formspree Implementation

If Netlify Functions are too complex, use Formspree:

  1. Create account at formspree.io
  2. Create new form
  3. Get form endpoint URL
  4. In assessment-engine.js, change submission:
async submitToBackend(data) {
  const response = await fetch('https://formspree.io/f/YOUR_FORM_ID', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
  return response.ok;
}
  1. Formspree handles:

Next Phase: Email Sequences

Once quiz is working, set up automated email sequences:

Tools Options:

  1. ConvertKit - Best for creators, email sequences
  2. Mailchimp - All-in-one, free tier
  3. SendGrid - Developer-friendly
  4. ActiveCampaign - Advanced automation

Email Flow:

  1. Immediate: PDF report + welcome
  2. Day 3: Story/testimonial
  3. Day 7: Educational content on their barrier
  4. Day 10: (High-intent only) Personal video
  5. Day 14: Case study
  6. Day 21: Final invitation

Analytics to Track

Google Analytics Events:

Metrics Dashboard:


Cost Breakdown

Option 1: Netlify + SendGrid (RECOMMENDED)

Option 2: Formspree

Option 3: Google Sheets + Apps Script


Support & Troubleshooting

Common Issues:

Quiz not loading:

Progress not saving:

Submission failing:

Email not sending:


Future Enhancements


Would you like me to:

  1. Create the complete assessment-engine.js file?
  2. Set up the Netlify function code?
  3. Create email templates?
  4. Build a simpler version with Formspree?