This workflow corresponds to n8n.io template #12012 — we link there as the canonical source.
This workflow follows the Chainllm → Form Trigger recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "e666c5b3-e7f5-4f6e-8767-b485e72339ea",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1248,
976
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {
"timeout": 500000
},
"responsesApiEnabled": false
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "570acae6-1be7-4cd4-af09-fcfd6244e3c3",
"name": "Create Form",
"type": "n8n-nodes-base.httpRequest",
"position": [
1648,
752
],
"parameters": {
"url": "https://forms.googleapis.com/v1/forms",
"method": "POST",
"options": {},
"jsonBody": "{\n \"info\": {\n \"title\": \"My Quiz Form\",\n \"documentTitle\": \"Quiz Form\"\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "4b018621-7e70-4d5e-8022-ae01d110f44a",
"name": "Enable Quiz Mode",
"type": "n8n-nodes-base.httpRequest",
"position": [
1872,
752
],
"parameters": {
"url": "=https://forms.googleapis.com/v1/forms/{{ $('Create Form').item.json.formId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "{\n \"requests\": [\n {\n \"updateSettings\": {\n \"settings\": {\n \"quizSettings\": {\n \"isQuiz\": true\n }\n },\n \"updateMask\": \"quizSettings.isQuiz\"\n }\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "a39bee23-7485-4771-b7e7-7f076479c65d",
"name": "Add Questions",
"type": "n8n-nodes-base.httpRequest",
"position": [
2080,
752
],
"parameters": {
"url": "=https://forms.googleapis.com/v1/forms/{{ $('Create Form').item.json.formId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={{ $('Questions Generate').item.json.output }}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "050e7e42-7a50-4fcd-9bb0-15c1f15db063",
"name": "Add Student Details",
"type": "n8n-nodes-base.httpRequest",
"position": [
2288,
752
],
"parameters": {
"url": "=https://forms.googleapis.com/v1/forms/{{ $('Create Form').item.json.formId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"requests\": [\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Student Information\",\n \"description\": \"Please fill in your details before starting the quiz\",\n \"pageBreakItem\": {}\n },\n \"location\": { \"index\": 0 }\n }\n },\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Full Name\",\n \"questionItem\": {\n \"question\": {\n \"required\": true,\n \"textQuestion\": { \"paragraph\": false }\n }\n }\n },\n \"location\": { \"index\": 1 }\n }\n },\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Email Address\",\n \"questionItem\": {\n \"question\": {\n \"required\": true,\n \"textQuestion\": { \"paragraph\": false }\n }\n }\n },\n \"location\": { \"index\": 2 }\n }\n },\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Student ID\",\n \"questionItem\": {\n \"question\": {\n \"required\": true,\n \"textQuestion\": { \"paragraph\": false }\n }\n }\n },\n \"location\": { \"index\": 3 }\n }\n },\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Class/Grade\",\n \"questionItem\": {\n \"question\": {\n \"required\": true,\n \"textQuestion\": { \"paragraph\": false }\n }\n }\n },\n \"location\": { \"index\": 4 }\n }\n },\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Quiz Questions\",\n \"description\": \"Answer all questions to the best of your ability\",\n \"pageBreakItem\": {}\n },\n \"location\": { \"index\": 5 }\n }\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleOAuth2Api"
},
"typeVersion": 4.3
},
{
"id": "17ae5873-6130-4162-8111-3d94ef3ed5b7",
"name": "Extract from File",
"type": "n8n-nodes-base.extractFromFile",
"position": [
1040,
752
],
"parameters": {
"options": {},
"operation": "pdf",
"binaryPropertyName": "PDF"
},
"typeVersion": 1.1
},
{
"id": "d820213b-65bd-44ee-9113-ee8326d87fd4",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1408,
976
],
"parameters": {
"jsonSchemaExample": "{\n \"requests\": [\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Question text here?\",\n \"questionItem\": {\n \"question\": {\n \"required\": true,\n \"grading\": {\n \"pointValue\": 1,\n \"correctAnswers\": {\n \"answers\": [\n {\n \"value\": \"Correct answer text\"\n }\n ]\n },\n \"whenRight\": {\n \"text\": \"Correct! Well done.\"\n },\n \"whenWrong\": {\n \"text\": \"Incorrect. The correct answer is [correct answer].\"\n }\n },\n \"choiceQuestion\": {\n \"type\": \"RADIO\",\n \"options\": [\n { \"value\": \"Option 1\" },\n { \"value\": \"Option 2 (correct)\" },\n { \"value\": \"Option 3\" },\n { \"value\": \"Option 4\" }\n ],\n \"shuffle\": true\n }\n }\n }\n },\n \"location\": {\n \"index\": 0\n }\n }\n }\n ]\n}"
},
"notesInFlow": false,
"typeVersion": 1.3
},
{
"id": "dc632b1e-4643-4628-bfc5-2beb3787a2ab",
"name": "On form submission",
"type": "n8n-nodes-base.formTrigger",
"position": [
816,
752
],
"parameters": {
"options": {},
"formTitle": "PDF",
"formFields": {
"values": [
{
"fieldType": "file",
"fieldLabel": "PDF",
"requiredField": true,
"acceptFileTypes": ".pdf"
},
{
"fieldLabel": "How many questions would you like to have in the quiz?",
"placeholder": "e.g. 20",
"requiredField": true
}
]
}
},
"typeVersion": 2.3
},
{
"id": "8c0b57dd-9716-45a1-beb4-c66805a82fe0",
"name": "Questions Generate",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1264,
752
],
"parameters": {
"text": "=You are an AI Teacher Agent specialized in creating quiz questions from educational content.\n\nInput : {{ $json.text }}\n\nYour Task:\nGenerate multiple-choice quiz questions with correct answers that can be directly used with Google Forms API.\nRequirements:\n\nCreate at least {{ $('On form submission').item.json['How many questions would you like to have in the quiz?'] }} questions based on the content\nEach question must have exactly 4 options\nMark one option as the correct answer\nEach question is worth 1 point\nFocus on key concepts, important facts, and learning objectives\nUse clear, student-friendly language\nAvoid ambiguous or trick questions\nDon't repeat similar questions\n\nReturn a valid JSON object with this exact structure:\n{\n \"requests\": [\n {\n \"createItem\": {\n \"item\": {\n \"title\": \"Question text here?\",\n \"questionItem\": {\n \"question\": {\n \"required\": true,\n \"grading\": {\n \"pointValue\": 1,\n \"correctAnswers\": {\n \"answers\": [\n {\n \"value\": \"Correct answer text\"\n }\n ]\n },\n \"whenRight\": {\n \"text\": \"Correct! Well done.\"\n },\n \"whenWrong\": {\n \"text\": \"Incorrect. The correct answer is [correct answer].\"\n }\n },\n \"choiceQuestion\": {\n \"type\": \"RADIO\",\n \"options\": [\n { \"value\": \"Option 1\" },\n { \"value\": \"Option 2 (correct)\" },\n { \"value\": \"Option 3\" },\n { \"value\": \"Option 4\" }\n ],\n \"shuffle\": true\n }\n }\n }\n },\n \"location\": {\n \"index\": 0\n }\n }\n }\n ]\n}\n\nImportant Notes:\n\nThe correct answer in correctAnswers.answers[0].value must EXACTLY match one of the option values in options\nUse \"shuffle\": true to randomize option order for students\nCustomize whenWrong.text to include the correct answer\nIndex starts at 0 and increments for each question\nEnsure all JSON is properly formatted and valid\n\nQuestion Quality Guidelines:\n\nTest understanding, not just memorization\nUse varied question stems (What, Why, How, Which, etc.)\nInclude questions at different difficulty levels\nEnsure distractors (wrong answers) are plausible but clearly incorrect\nAvoid \"all of the above\" or \"none of the above\" options",
"batching": {},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.7
},
{
"id": "a6b1e730-7e2e-459a-a5a8-96d08998f346",
"name": "Set a Google Sheet Structure for all Questions",
"type": "n8n-nodes-base.code",
"position": [
2512,
752
],
"parameters": {
"jsCode": "// Get question array\nconst data = $('Questions Generate').first().json.output.requests;\n\n// Get quiz URL from previous node\nconst quizUrl = $('Create Form').first().json.responderUri|| \"\";\n\n// Prepare rows\nlet rows = [];\n\nfor (let i = 0; i < data.length; i++) {\n const req = data[i];\n\n const item = req.createItem.item;\n const question = item.title;\n const options = item.questionItem.question.choiceQuestion.options.map(o => o.value);\n const correctAnswer = item.questionItem.question.grading.correctAnswers.answers[0].value;\n\n rows.push({\n question: question,\n option1: options[0] || \"\",\n option2: options[1] || \"\",\n option3: options[2] || \"\",\n option4: options[3] || \"\",\n correct_answer: correctAnswer,\n\n // \u2b50 ONLY FIRST ROW gets quiz URL\n quiz_url: i === 0 ? quizUrl : \"\"\n });\n}\n\n// Return to Sheet node\nreturn rows.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "c54f04f2-9400-4c6c-83eb-506d9f387611",
"name": "Append All Questions",
"type": "n8n-nodes-base.googleSheets",
"position": [
2736,
752
],
"parameters": {
"columns": {
"value": {
"Option1": "={{ $json.option1 }}",
"Option2": "={{ $json.option2 }}",
"Option3": "={{ $json.option3 }}",
"Option4": "={{ $json.option4 }}",
"Question": "={{ $json.question }}",
"Quiz Url": "={{ $json.quiz_url }}",
"Correct_answer": "={{ $json.correct_answer }}"
},
"schema": [
{
"id": "Question",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Question",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Option1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Option1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Option2",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Option2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Option3",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Option3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Option4",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Option4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Correct_answer",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Correct_answer",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Quiz Url",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Quiz Url",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1003708851,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1mpAObyL-Un8_369o1omQSzr415lyW3HxstODO41DHTQ/edit#gid=1003708851",
"cachedResultName": "Quiz Form"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1mpAObyL-Un8_369o1omQSzr415lyW3HxstODO41DHTQ",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1mpAObyL-Un8_369o1omQSzr415lyW3HxstODO41DHTQ/edit?usp=drivesdk",
"cachedResultName": "My Quiz Form"
}
},
"typeVersion": 4.7
},
{
"id": "2054baf8-fbf1-4632-8646-675507bcabc7",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
352,
1120
],
"parameters": {
"color": 5,
"width": 400,
"content": "## Google sheet\n\nhttps://docs.google.com/spreadsheets/d/1mpAObyL-Un8_369o1omQSzr415lyW3HxstODO41DHTQ/edit?usp=sharing"
},
"typeVersion": 1
},
{
"id": "b9a56d7b-16bc-477b-8db5-f33d8c238fc6",
"name": "Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
352,
592
],
"parameters": {
"width": 404,
"height": 508,
"content": "## How it works\n\nThis workflow automatically generates Google Forms quizzes from PDF documents using AI. Upload a PDF and specify the number of questions\u2014the AI extracts content, creates multiple-choice questions with correct answers, builds a Google Form with student information fields, and logs all questions to a Google Sheet for record-keeping.\n\n## Setup steps\n\n1. **Connect credentials**: Add Google OAuth2 API credentials for form creation and Google Sheets OAuth2 for data logging\n2. **Add OpenAI API**: Configure OpenAI credentials for the AI model\n3. **Configure Google Sheet**: Update the sheet ID in \"Append All Questions\" node to your target spreadsheet\n4. **Test the form**: Submit a PDF through the form trigger URL to generate your first quiz"
},
"typeVersion": 1
},
{
"id": "9b2c0e2a-cf7a-4c48-86de-bb6ff89dee82",
"name": "Input Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
592
],
"parameters": {
"color": 7,
"width": 424,
"height": 364,
"content": "## Input Section\nForm trigger accepts PDF uploads and question count from users"
},
"typeVersion": 1
},
{
"id": "fb4c08fb-27c7-40f7-9179-d77504da3f48",
"name": "AI Processing Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
592
],
"parameters": {
"color": 7,
"width": 368,
"height": 588,
"content": "## AI Processing Section\nExtracts PDF text and uses OpenAI to generate structured quiz questions with answers"
},
"typeVersion": 1
},
{
"id": "82e3109f-7e91-4ed1-913a-ea65944d1910",
"name": "Form Creation Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
1584,
592
],
"parameters": {
"color": 7,
"width": 852,
"height": 380,
"content": "## Form Creation Section\nBuilds Google Form with quiz mode, adds AI-generated questions and student info fields"
},
"typeVersion": 1
},
{
"id": "9d3c95c2-cfc6-4d44-8114-62239cc45b9d",
"name": "Output Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
2448,
592
],
"parameters": {
"color": 7,
"width": 472,
"height": 380,
"content": "## Output Section\nFormats and logs all questions with answers to Google Sheets for tracking"
},
"typeVersion": 1
}
],
"connections": {
"Create Form": {
"main": [
[
{
"node": "Enable Quiz Mode",
"type": "main",
"index": 0
}
]
]
},
"Add Questions": {
"main": [
[
{
"node": "Add Student Details",
"type": "main",
"index": 0
}
]
]
},
"Enable Quiz Mode": {
"main": [
[
{
"node": "Add Questions",
"type": "main",
"index": 0
}
]
]
},
"Extract from File": {
"main": [
[
{
"node": "Questions Generate",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Questions Generate",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"On form submission": {
"main": [
[
{
"node": "Extract from File",
"type": "main",
"index": 0
}
]
]
},
"Questions Generate": {
"main": [
[
{
"node": "Create Form",
"type": "main",
"index": 0
}
]
]
},
"Add Student Details": {
"main": [
[
{
"node": "Set a Google Sheet Structure for all Questions",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Questions Generate",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Set a Google Sheet Structure for all Questions": {
"main": [
[
{
"node": "Append All Questions",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Teachers, coaches, and educators spend hours manually creating quizzes from study notes and PDFs. This workflow eliminates that effort by using AI to convert PDF study material into fully functional quizzes, complete with scoring, student tracking, and Google Form integration —…
Source: https://n8n.io/workflows/12012/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
> *Trend-style celebrity selfie videos
The workflow runs every hour with a randomized delay of 5–20 minutes to help distribute load. It records the exact date and time a lead is emailed so you can track outreach. Follow-ups are automatical
This workflow is perfect for graphic designers, creative agencies, marketing teams, or freelancers who regularly use AI-generated images in their projects. It's specifically beneficial for teams that
This workflow is designed for professionals and teams seeking to scale their B2B research with comprehensive company intelligence. It automates the full prospect analysis process — from extracting con
This n8n template automates targeted lead discovery, AI-driven data structuring, and personalized cold-email sending at controlled intervals. It’s ideal for sales teams, founders, and agencies that wa