AutomationFlowsEmail & Gmail › Automated Student Progress Reports From Lms to Parents via Gmail & Google Sheets

Automated Student Progress Reports From Lms to Parents via Gmail & Google Sheets

ByOneclick AI Squad @oneclick-ai on n8n.io

This n8n workflow automatically creates and sends regular performance summaries to parents using data from a Learning Management System (LMS). It pulls student grades and attendance, formats them into easy-to-read reports, and emails them without any manual work. Fully…

Cron / scheduled trigger★★★★☆ complexity11 nodesGoogle SheetsHTTP RequestGmail
Email & Gmail Trigger: Cron / scheduled Nodes: 11 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #6998 — we link there as the canonical source.

This workflow follows the Gmail → Google Sheets 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 →

Download .json
{
  "id": "rumCZInCSooKZgBp",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Student Academic Progress Report Generator",
  "tags": [],
  "nodes": [
    {
      "id": "3df9207a-f7cb-421d-ba09-c8933669c09d",
      "name": "Get Students List",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -240,
        -160
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "Students",
          "cachedResultName": "Students"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_STUDENT_SHEET_ID",
          "cachedResultName": "Student Database"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "b48f5de6-7a90-4a40-8f93-4bd3c2ab4d15",
      "name": "Split Students for Processing",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -20,
        -160
      ],
      "parameters": {
        "options": {},
        "batchSize": 5
      },
      "typeVersion": 3
    },
    {
      "id": "441a7ac4-ef43-4692-b5b2-eaf3bf2ebac7",
      "name": "Fetch LMS Academic Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        200,
        -160
      ],
      "parameters": {
        "url": "={{ $credentials.lmsApi.baseUrl }}/api/students/{{ $json.student_id }}/grades",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "period",
              "value": "current_week"
            },
            {
              "name": "include_assignments",
              "value": "true"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{ $credentials.lmsApi.apiToken }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7237f988-66a8-4e45-b6ac-2746485e7282",
      "name": "Process Academic Data",
      "type": "n8n-nodes-base.code",
      "position": [
        420,
        -160
      ],
      "parameters": {
        "jsCode": "const studentData = $input.first().json;\nconst lmsData = $input.last().json;\n\nconst grades = lmsData.grades || [];\nconst totalGrade = grades.reduce((sum, grade) => sum + parseFloat(grade.score || 0), 0);\nconst averageGrade = grades.length > 0 ? (totalGrade / grades.length).toFixed(2) : 'N/A';\n\nconst assignments = lmsData.assignments || [];\nconst completedAssignments = assignments.filter(a => a.status === 'completed').length;\nconst completionRate = assignments.length > 0 ? ((completedAssignments / assignments.length) * 100).toFixed(1) : '0';\n\nconst recentGrades = grades.slice(-3).map(g => parseFloat(g.score || 0));\nlet trend = 'Stable';\nif (recentGrades.length >= 2) {\n  const firstHalf = recentGrades.slice(0, Math.floor(recentGrades.length/2));\n  const secondHalf = recentGrades.slice(Math.floor(recentGrades.length/2));\n  const firstAvg = firstHalf.reduce((a,b) => a+b, 0) / firstHalf.length;\n  const secondAvg = secondHalf.reduce((a,b) => a+b, 0) / secondHalf.length;\n  \n  if (secondAvg > firstAvg + 5) trend = 'Improving';\n  else if (secondAvg < firstAvg - 5) trend = 'Declining';\n}\n\nconst attendanceRate = lmsData.attendance ? ((lmsData.attendance.present / lmsData.attendance.total) * 100).toFixed(1) : 'N/A';\n\nconst subjectsNeedingAttention = grades.filter(grade => parseFloat(grade.score || 0) < 70).map(grade => grade.subject).slice(0, 3);\n\nreturn [{\n  json: {\n    student_name: studentData.student_name,\n    student_id: studentData.student_id,\n    parent_email: studentData.parent_email,\n    grade_level: studentData.grade_level,\n    report_date: new Date().toISOString().split('T')[0],\n    overall_grade: averageGrade,\n    assignment_completion_rate: completionRate + '%',\n    attendance_rate: attendanceRate + '%',\n    performance_trend: trend,\n    subjects_needing_attention: subjectsNeedingAttention.join(', ') || 'None',\n    total_assignments: assignments.length,\n    completed_assignments: completedAssignments,\n    recent_grades: recentGrades.join(', '),\n    teacher_comments: lmsData.teacher_comments || 'No recent comments'\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "3035a22d-352e-47ed-9628-cf72675f344f",
      "name": "Generate HTML Report",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        -160
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\n\nconst htmlTemplate = `<!DOCTYPE html>\n<html>\n<head>\n    <style>\n        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }\n        .container { max-width: 600px; margin: 0 auto; padding: 20px; }\n        .header { background-color: #4CAF50; color: white; padding: 20px; text-align: center; border-radius: 5px; }\n        .content { background-color: #f9f9f9; padding: 20px; margin: 20px 0; border-radius: 5px; }\n        .metric { display: inline-block; margin: 10px; padding: 15px; background-color: white; border-radius: 5px; text-align: center; min-width: 120px; }\n        .metric-value { font-size: 24px; font-weight: bold; color: #4CAF50; }\n        .metric-label { font-size: 12px; color: #666; }\n        .alert { background-color: #fff3cd; border: 1px solid #ffeaa7; padding: 10px; border-radius: 5px; margin: 10px 0; }\n        .footer { text-align: center; font-size: 12px; color: #666; margin-top: 20px; }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <div class=\"header\">\n            <h1>\ud83d\udcda Weekly Academic Progress Report</h1>\n            <p>Student: ${data.student_name} | Grade: ${data.grade_level}</p>\n            <p>Report Date: ${data.report_date}</p>\n        </div>\n        <div class=\"content\">\n            <h2>\ud83d\udcca Performance Overview</h2>\n            <div style=\"text-align: center;\">\n                <div class=\"metric\">\n                    <div class=\"metric-value\">${data.overall_grade}</div>\n                    <div class=\"metric-label\">Overall Grade</div>\n                </div>\n                <div class=\"metric\">\n                    <div class=\"metric-value\">${data.assignment_completion_rate}</div>\n                    <div class=\"metric-label\">Assignments Completed</div>\n                </div>\n                <div class=\"metric\">\n                    <div class=\"metric-value\">${data.attendance_rate}</div>\n                    <div class=\"metric-label\">Attendance Rate</div>\n                </div>\n            </div>\n        </div>\n        <div class=\"content\">\n            <h2>\ud83d\udcc8 Performance Trend</h2>\n            <p>Current trend: <strong>${data.performance_trend}</strong></p>\n            <p><strong>Recent Grades:</strong> ${data.recent_grades || 'No recent grades available'}</p>\n        </div>\n        <div class=\"content\">\n            <h2>\ud83d\udcdd Assignment Status</h2>\n            <p><strong>Total Assignments:</strong> ${data.total_assignments}</p>\n            <p><strong>Completed:</strong> ${data.completed_assignments}</p>\n            <p><strong>Completion Rate:</strong> ${data.assignment_completion_rate}</p>\n        </div>\n        ${data.subjects_needing_attention && data.subjects_needing_attention !== 'None' ? `<div class=\"alert\"><h3>\u26a0\ufe0f Areas for Improvement</h3><p><strong>Subjects needing attention:</strong> ${data.subjects_needing_attention}</p></div>` : ''}\n        <div class=\"content\">\n            <h2>\ud83d\udcac Teacher Comments</h2>\n            <p>${data.teacher_comments}</p>\n        </div>\n        <div class=\"footer\">\n            <p>This report was automatically generated by the Academic Progress System.</p>\n            <p>For questions, please contact your child's teacher.</p>\n        </div>\n    </div>\n</body>\n</html>`;\n\nreturn [{\n  json: {\n    ...data,\n    html_report: htmlTemplate,\n    email_subject: `\ud83d\udcda Weekly Progress Report - ${data.student_name} (${data.report_date})`\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "167244cb-3eb0-45ae-bfd3-a4a70e3573a9",
      "name": "Send Email to Parents",
      "type": "n8n-nodes-base.gmail",
      "position": [
        860,
        -160
      ],
      "parameters": {
        "sendTo": "={{ $json.parent_email }}",
        "message": "={{ $json.html_report }}",
        "options": {
          "ccList": "user@example.com"
        },
        "subject": "={{ $json.email_subject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "ad762e3e-5680-47d8-98e2-b6ec9dffa028",
      "name": "Log Report Delivery",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1080,
        -160
      ],
      "parameters": {
        "columns": {
          "value": {
            "timestamp": "={{ $now.toISO() }}",
            "student_id": "={{ $json.student_id }}",
            "parent_email": "={{ $json.parent_email }}",
            "student_name": "={{ $json.student_name }}",
            "overall_grade": "={{ $json.overall_grade }}",
            "delivery_status": "Sent Successfully"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "student_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Student ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "student_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Student Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "parent_email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Parent Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "overall_grade",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Overall Grade",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "delivery_status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Delivery Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "Delivery_Log",
          "cachedResultName": "Delivery Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_LOG_SHEET_ID",
          "cachedResultName": "Report Logs"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "d5956d08-fcc2-49ee-91c2-00350e228f39",
      "name": "Send Admin Summary",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1300,
        -160
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<h2>\ud83d\udcda Student Progress Report Summary</h2><br><strong>Date:</strong> {{ $now.format('MMMM DD, YYYY') }}<br><strong>Status:</strong> \u2705 All weekly progress reports sent successfully<br><br><em>Automated summary from Student Progress Report Generator</em>",
        "options": {},
        "subject": "\ud83d\udcca Weekly Student Progress Reports Complete"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "516a6491-f5fe-4800-aba5-06312a441716",
      "name": "Workflow Info",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -660,
        -640
      ],
      "parameters": {
        "width": 600,
        "height": 300,
        "content": "## \ud83d\udcda Student Academic Progress Report Generator\n\n### Features:\n\u2022 Weekly automated reports\n\u2022 LMS data integration\n\u2022 Parent email notifications\n\u2022 Performance trend analysis\n\u2022 HTML formatted reports\n\u2022 Admin summaries\n\n### Schedule: Every Monday at 9 AM"
      },
      "typeVersion": 1
    },
    {
      "id": "8fb08929-6149-49d9-bc60-5b0713074df7",
      "name": "Setup Required",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20,
        -720
      ],
      "parameters": {
        "color": 3,
        "width": 420,
        "height": 200,
        "content": "## \u2699\ufe0f Setup Required\n\n1. Replace YOUR_STUDENT_SHEET_ID\n2. Replace YOUR_LOG_SHEET_ID\n3. Configure LMS API credentials\n4. Set up Gmail credentials\n5. Update email addresses"
      },
      "typeVersion": 1
    },
    {
      "id": "b41641c9-aef5-49a8-96ff-dc4ba3a10591",
      "name": "Weekly Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -480,
        -160
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f2deb505-6c16-43dd-9322-c18de89c5684",
  "connections": {
    "Get Students List": {
      "main": [
        [
          {
            "node": "Split Students for Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Report Delivery": {
      "main": [
        [
          {
            "node": "Send Admin Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate HTML Report": {
      "main": [
        [
          {
            "node": "Send Email to Parents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Academic Data": {
      "main": [
        [
          {
            "node": "Generate HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email to Parents": {
      "main": [
        [
          {
            "node": "Log Report Delivery",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch LMS Academic Data": {
      "main": [
        [
          {
            "node": "Process Academic Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get Students List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Students for Processing": {
      "main": [
        [
          {
            "node": "Fetch LMS Academic Data",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This n8n workflow automatically creates and sends regular performance summaries to parents using data from a Learning Management System (LMS). It pulls student grades and attendance, formats them into easy-to-read reports, and emails them without any manual work. Fully…

Source: https://n8n.io/workflows/6998/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1
Email & Gmail

Looking for a way to track GitHub bounty issues automatically and get notified in real time? This GitHub Bounty Tracker workflow monitors repositories for issues labeled 💎 Bounty, logs them in Google

Google Sheets, HTTP Request, WhatsApp +1
Email & Gmail

This workflow automatically sends a beautifully designed HTML newsletter every Sunday at 8 AM, featuring products currently on sale from your Algolia-powered e-commerce store.

Google Sheets, HTTP Request, Gmail
Email & Gmail

This n8n template demonstrates how to build a Auto Lead Gen & Outreach System for Local Businesses specifically designed to help businesses that don’t have a website yet.

Google Sheets, HTTP Request, Google Drive +1
Email & Gmail

I created this workflow with care for marketing professionals and agencies who manage multiple Meta Ads (Facebook) accounts and want to track ad account balances automatically — no more logging in eve

HTTP Request, Google Sheets, Gmail