Implementing Quizzes and Surveys
Quizzes and surveys gather feedback, run tests, help users choose products. Key requirements: flexible question structure, support different answer types, display results.
Database Structure
CREATE TABLE quizzes (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
type VARCHAR(50) NOT NULL DEFAULT 'survey', -- survey|quiz|poll
settings JSONB NOT NULL DEFAULT '{}', -- show_results, randomize, time_limit
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE questions (
id SERIAL PRIMARY KEY,
quiz_id INTEGER REFERENCES quizzes(id) ON DELETE CASCADE,
type VARCHAR(50) NOT NULL, -- text|choice|multiple|rating|nps
title TEXT NOT NULL,
required BOOLEAN DEFAULT true,
order_index INTEGER NOT NULL,
metadata JSONB DEFAULT '{}'
);
CREATE TABLE answers (
id SERIAL PRIMARY KEY,
question_id INTEGER REFERENCES questions(id),
text TEXT NOT NULL,
order_index INTEGER
);
CREATE TABLE responses (
id SERIAL PRIMARY KEY,
quiz_id INTEGER REFERENCES quizzes(id),
user_id INTEGER REFERENCES users(id),
ip_address INET,
data JSONB NOT NULL, -- {question_id: answer_value, ...}
completed_at TIMESTAMPTZ
);
React Component
function QuizForm({ quiz }: { quiz: Quiz }) {
const [responses, setResponses] = useState<Record<string, any>>({});
const handleSubmit = async () => {
const res = await fetch(`/api/quizzes/${quiz.id}/responses`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(responses),
});
if (res.ok) alert('Thank you for your response!');
};
return (
<form onSubmit={handleSubmit}>
{quiz.questions.map(q => (
<QuestionField
key={q.id}
question={q}
onChange={(val) => setResponses(prev => ({...prev, [q.id]: val}))}
/>
))}
<button type="submit">Submit</button>
</form>
);
}
Timeline
Basic quiz setup with 3-4 question types and result display: 2-3 days. Advanced features (logic branching, A/B testing): 5-7 days.







