{
  "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
          }
        ]
      ]
    }
  }
}