What You'll Build
A complete event registration system with attendee tracking, ticket types, and real-time updates. Manage everything from a Google Sheet without complex event platforms.
Step 1: Create Your Event Sheet
Set up a Google Sheet with these columns:
- Name - Attendee full name
- Email - Contact email
- Event - Event name
- Ticket Type - Early Bird, Regular, VIP, etc.
- Date Registered - Registration timestamp
- Confirmed - Yes/No confirmation status
Step 2: Design Your Registration Form
Use the HTML template to create an attractive registration page. Customize ticket types, pricing, and event details to match your event.
Step 3: Handle Registrations
The JavaScript code captures form submissions and saves them to your Sheet. Each registration is timestamped and initially marked as unconfirmed.
Step 4: Manage Attendees
View and manage registrations directly in your Google Sheet. Update the Confirmed column to Yes after payment or manual approval.
Step 5: Display Attendee Count
Use the attendee widget snippet to show real-time registration numbers on your event page. Great for social proof!
Use Cases
- Meetups - Track RSVPs for local community events
- Conferences - Manage multi-track event registrations
- Workshops - Limit capacity with real-time attendee counts
- Webinars - Collect registrations and send reminders
Advanced Features
- Set up webhooks to send confirmation emails automatically
- Integrate with payment processors (Stripe, PayPal)
- Add QR code generation for check-in
- Create a check-in app using the API
- Send automated reminders before the event
- Track attendance and no-shows
- Export attendee lists for badges and certificates
Pro Tips
- Use Google Sheets formulas to auto-calculate ticket revenue
- Add conditional formatting to highlight VIP tickets
- Create a separate sheet for waitlist management
- Use data validation to standardize ticket types
<!DOCTYPE html>
<html>
<head>
<title>Event Registration</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
.event-header { text-align: center; margin-bottom: 30px; }
.event-header h1 { color: #667eea; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input, select { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
.ticket-options { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ticket-option { padding: 15px; border: 2px solid #ddd; border-radius: 8px; cursor: pointer; text-align: center; }
.ticket-option.selected { border-color: #667eea; background: #f0f4ff; }
.ticket-option .price { font-size: 1.5rem; color: #667eea; font-weight: bold; }
button { width: 100%; background: #667eea; color: white; padding: 15px; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; font-weight: bold; }
button:hover { background: #5568d3; }
.success { background: #d4edda; color: #155724; padding: 15px; border-radius: 4px; margin-top: 20px; }
</style>
</head>
<body>
<div class="event-header">
<h1>📅 Tech Conference 2024</h1>
<p>Join us for an amazing day of talks and networking!</p>
</div>
<form id="registrationForm">
<div class="form-group">
<label>Full Name</label>
<input type="text" name="name" required>
</div>
<div class="form-group">
<label>Email Address</label>
<input type="email" name="email" required>
</div>
<div class="form-group">
<label>Select Ticket Type</label>
<div class="ticket-options">
<div class="ticket-option" data-ticket="Early Bird">
<div>Early Bird</div>
<div class="price">$49</div>
</div>
<div class="ticket-option" data-ticket="Regular">
<div>Regular</div>
<div class="price">$79</div>
</div>
</div>
<input type="hidden" name="ticket" required>
</div>
<button type="submit">Register Now</button>
</form>
<div id="status"></div>
<script src="registration.js"></script>
</body>
</html>
const API_URL = 'https://sheetapi.pro/api/v1/sheets/YOUR_SHEET_ID/data';
const API_KEY = 'YOUR_API_KEY';
const EVENT_NAME = 'Tech Conference 2024';
// Ticket selection
document.querySelectorAll('.ticket-option').forEach(option => {
option.addEventListener('click', function() {
document.querySelectorAll('.ticket-option').forEach(o => o.classList.remove('selected'));
this.classList.add('selected');
document.querySelector('input[name="ticket"]').value = this.dataset.ticket;
});
});
// Form submission
document.getElementById('registrationForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = {
Name: formData.get('name'),
Email: formData.get('email'),
Event: EVENT_NAME,
'Ticket Type': formData.get('ticket'),
'Date Registered': new Date().toISOString(),
Confirmed: 'No'
};
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify(data)
});
if (response.ok) {
document.getElementById('status').innerHTML =
'<div class="success">✓ Registration successful! Check your email for confirmation.</div>';
e.target.reset();
document.querySelectorAll('.ticket-option').forEach(o => o.classList.remove('selected'));
} else {
throw new Error('Registration failed');
}
} catch (error) {
document.getElementById('status').innerHTML =
'<div style="color:red; padding:15px; background:#f8d7da; border-radius:4px;">✗ Registration failed. Please try again.</div>';
}
});
// Attendee list widget (read-only view)
const API_URL = 'https://sheetapi.pro/api/v1/sheets/YOUR_SHEET_ID/data';
const API_KEY = 'YOUR_API_KEY';
async function loadAttendees() {
try {
const response = await fetch(API_URL, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const data = await response.json();
const attendees = data.data || [];
const confirmedCount = attendees.filter(a => a.Confirmed === 'Yes').length;
document.getElementById('attendeeCount').textContent = confirmedCount;
const listHtml = attendees
.filter(a => a.Confirmed === 'Yes')
.map(a => `
<div class="attendee">
<strong>${a.Name}</strong>
<span class="ticket-badge">${a['Ticket Type']}</span>
</div>
`).join('');
document.getElementById('attendeeList').innerHTML = listHtml;
} catch (error) {
console.error('Failed to load attendees:', error);
}
}
loadAttendees();
// Refresh every 30 seconds
setInterval(loadAttendees, 30000);
from flask import Flask, request, jsonify
import requests
from datetime import datetime
app = Flask(__name__)
SHEET_ID = 'YOUR_SHEET_ID'
API_KEY = 'YOUR_API_KEY'
API_URL = f'https://sheetapi.pro/api/v1/sheets/{SHEET_ID}/data'
@app.route('/register', methods=['POST'])
def register():
data = request.json
payload = {
'Name': data.get('name'),
'Email': data.get('email'),
'Event': data.get('event', 'My Event'),
'Ticket Type': data.get('ticket_type'),
'Date Registered': datetime.now().isoformat(),
'Confirmed': 'No'
}
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {API_KEY}'
}
response = requests.post(API_URL, json=payload, headers=headers)
if response.status_code == 200:
# TODO: Send confirmation email
return jsonify({
'success': True,
'message': 'Registration successful'
})
else:
return jsonify({
'success': False,
'error': 'Registration failed'
}), 500
@app.route('/attendees', methods=['GET'])
def get_attendees():
headers = {'Authorization': f'Bearer {API_KEY}'}
response = requests.get(API_URL, headers=headers)
if response.status_code == 200:
attendees = response.json().get('data', [])
confirmed = [a for a in attendees if a.get('Confirmed') == 'Yes']
return jsonify({
'success': True,
'total': len(attendees),
'confirmed': len(confirmed),
'attendees': confirmed
})
else:
return jsonify({'success': False}), 500
if __name__ == '__main__':
app.run(debug=True)
<?php
// event-registration.php
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
$payload = [
'Name' => $data['name'],
'Email' => $data['email'],
'Event' => $data['event'] ?? 'My Event',
'Ticket Type' => $data['ticket_type'],
'Date Registered' => date('c'),
'Confirmed' => 'No'
];
$ch = curl_init('https://sheetapi.pro/api/v1/sheets/YOUR_SHEET_ID/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer YOUR_API_KEY'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
// TODO: Send confirmation email
echo json_encode(['success' => true, 'message' => 'Registered successfully']);
} else {
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Registration failed']);
}
}
?>
# Register a new attendee
curl -X POST https://sheetapi.pro/api/v1/sheets/YOUR_SHEET_ID/data \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"Name": "Jane Smith",
"Email": "jane@example.com",
"Event": "Tech Conference 2024",
"Ticket Type": "Early Bird",
"Date Registered": "2024-01-15T10:30:00Z",
"Confirmed": "No"
}'
# Get all attendees
curl -X GET https://sheetapi.pro/api/v1/sheets/YOUR_SHEET_ID/data \
-H "Authorization: Bearer YOUR_API_KEY"
# Update confirmation status (requires row ID)
curl -X PATCH https://sheetapi.pro/api/v1/sheets/YOUR_SHEET_ID/data/5 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"Confirmed": "Yes"}'