{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "be3e62b9-5bd4-4ea5-a48a-b034a0f164ca",
      "name": "Save to Remove Background",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1168,
        192
      ],
      "parameters": {
        "name": "={{ $('Loop Over Original Files').item.json.name }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1fHs5mRfcw5Ngd7XlWLIDAtDl-jqFwDS8",
          "cachedResultUrl": "",
          "cachedResultName": "Compressed"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "6e535295-a2b0-40cb-9ac4-0a000bf17d96",
      "name": "Get all files",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        96,
        288
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "1yg0nahSLFReH5Ik-caVqO2AGC2Nll4Fx",
            "cachedResultUrl": "",
            "cachedResultName": "Image Compression"
          },
          "whatToSearch": "files"
        },
        "options": {},
        "resource": "fileFolder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "559ee1f9-6f93-4b05-8a4d-3702b68db6b6",
      "name": "Daily at 08:00 am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -272,
        384
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4726eaa0-6726-42e1-8869-d4e7ae3a11cd",
      "name": "Tiny URL API Call",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        752,
        112
      ],
      "parameters": {
        "url": "https://api.tinify.com/shrink",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "image/png, application/json"
            }
          ]
        },
        "inputDataFieldName": "data"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": true,
      "typeVersion": 4.2
    },
    {
      "id": "6c1b3c2d-9d17-4c8c-b232-6ea2c8239751",
      "name": "Load Raw Image",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        528,
        112
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "61712bd4-7b3f-45ab-85ce-d6f389bfb98f",
      "name": "Download Compressed Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        976,
        112
      ],
      "parameters": {
        "url": "={{ $json.output.url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "af8fdf34-004b-459b-98a4-c1de21dfce50",
      "name": "Move Files to the Folder /Original",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        736,
        464
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "17WuxNpiiSZ6VJY1QTUcrvy5er-Neklqu",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "operation": "move"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "dba1c9be-4681-4a6c-9391-c283ae6b5232",
      "name": "Loop Over Processed Files",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        320,
        496
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "45fd4fd1-5542-461d-995f-9907fca4c91f",
      "name": "Loop Over Original Files",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        304,
        192
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c94d5cec-5cc0-467f-a7e0-544da6e8a470",
      "name": "Generate Processing Id",
      "type": "n8n-nodes-base.set",
      "position": [
        -48,
        384
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7e591f43-a863-4cda-bb88-4ee7377b41af",
              "name": "processing_id",
              "type": "string",
              "value": "={{ $execution.id.toString().padStart(10, '0') }}"
            }
          ]
        }
      },
      "notesInFlow": true,
      "typeVersion": 3.4
    },
    {
      "id": "b2cf7310-e8be-4dc9-85b1-c577d154fde5",
      "name": "Processing Logs",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1312,
        80
      ],
      "parameters": {
        "columns": {
          "value": {
            "imageId": "={{ $('Load Raw Image').item.json.id }}",
            "fileName": "={{ $('Load Raw Image').item.json.name }}",
            "outputUrl": "={{ $('Tiny URL API Call').item.json.output.url }}",
            "originalSize": "={{ $('Tiny URL API Call').item.json.input.size }}",
            "processingId": "={{ $('Generate Processing Id').item.json.processing_id }}",
            "compressedSize": "={{ $('Tiny URL API Call').item.json.output.size }}"
          },
          "schema": [
            {
              "id": "fileName",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "fileName",
              "defaultMatch": false
            },
            {
              "id": "originalSize",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "originalSize",
              "defaultMatch": false
            },
            {
              "id": "compressedSize",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "compressedSize",
              "defaultMatch": false
            },
            {
              "id": "imageId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "imageId",
              "defaultMatch": false
            },
            {
              "id": "outputUrl",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "outputUrl",
              "defaultMatch": false
            },
            {
              "id": "processingId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "processingId",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": "Image Compression"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "15145b80-ff7b-422b-ad98-9a74e748046b",
      "name": "Generate Report",
      "type": "n8n-nodes-base.code",
      "position": [
        -64,
        720
      ],
      "parameters": {
        "jsCode": "const data = items.map(i => i.json);\nconst toKb = n => (Number(n) / 1024).toFixed(1);\nconst processingId = $input.first().json.processingId;\n\nconst totalSaved = data.reduce(\n  (s, d) => s + (Number(d.originalSize) - Number(d.compressedSize)),\n  0\n);\n\nconst rows = data.map(d => `\n  <tr>\n    <td style=\"padding:8px;border-bottom:1px solid #e5e7eb;\">${d.fileName}</td>\n    <td style=\"padding:8px;border-bottom:1px solid #e5e7eb;text-align:right;\">\n      ${toKb(d.originalSize)} KB\n    </td>\n    <td style=\"padding:8px;border-bottom:1px solid #e5e7eb;text-align:right;\">\n      ${toKb(d.compressedSize)} KB\n    </td>\n  </tr>\n`).join('');\n\nconst html = `\n  <div style=\"font-family:Arial,sans-serif;max-width:600px;margin:0 auto;line-height:1.5;\">\n    <h2 style=\"color:#0b7a4b;margin-bottom:4px;\">LogiGreen Image Compressor Bot</h2>\n    <p style=\"margin-top:0;font-size:14px;\">\n      For more details about the solution: \n      <a href=\"https://logi-green.com\" style=\"color:#0b7a4b;text-decoration:none;\">\n        LogiGreen\n      </a>.\n    </p>\n\n    <p><strong>Processing ID:</strong> ${processingId}</p>\n    <p><strong>Images processed:</strong> ${data.length}</p>\n\n    <table style=\"width:100%;border-collapse:collapse;font-size:13px;\">\n      <thead>\n        <tr style=\"background:#f3f4f6;\">\n          <th style=\"text-align:left;padding:8px;border-bottom:1px solid #e5e7eb;\">File</th>\n          <th style=\"text-align:right;padding:8px;border-bottom:1px solid #e5e7eb;\">Original</th>\n          <th style=\"text-align:right;padding:8px;border-bottom:1px solid #e5e7eb;\">Compressed</th>\n        </tr>\n      </thead>\n      <tbody>${rows}</tbody>\n    </table>\n\n    <p style=\"margin-top:12px;\">\n      <strong>Total saved:</strong> ${toKb(totalSaved)} KB (${totalSaved.toLocaleString()} bytes)\n    </p>\n\n    <p style=\"font-size:12px;color:#6b7280;\">\n      This email was automatically generated by the LogiGreen Image Compressor Bot\n      to help keep your product pages fast and SEO-friendly.\n    </p>\n  </div>\n`;\n\nreturn [\n  {\n    json: {\n      html,\n      processingId,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0e0808a0-016b-46a4-be16-a461e6fa8e7f",
      "name": "Collect Logs",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -256,
        720
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "processingId",
              "keyValue": "={{ $('Generate Processing Id').item.json.processing_id }}"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": "Image Compression"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c2140aaa-4c2c-40b6-8568-5cb6612bc101",
      "name": "Send Report",
      "type": "n8n-nodes-base.gmail",
      "position": [
        112,
        720
      ],
      "parameters": {
        "sendTo": "l<SET_YOUR_EMAIL>",
        "message": "={{ $json.html }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=Image Compression Report - {{ $json.processingId }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "notesInFlow": true,
      "typeVersion": 2.1
    },
    {
      "id": "68de5d92-ff4e-434c-95a5-2f0002096e6e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        64
      ],
      "parameters": {
        "width": 544,
        "height": 784,
        "content": "## Image Compressor using Tinyfy API\n\n### How it works\n1. A schedule trigger runs every morning at 08:00 and generates a unique `processingId` for the execution.\n2. The workflow lists all images in your Google Drive **Input** folder that need to be compressed.\n3. Each file is downloaded and sent to the **TinyPNG/Tinify** API.\n4. The compressed image is downloaded and saved into the **Compressed** folder in Google Drive.\n5. The original files are moved to the **Original Images** archive folder.\n6. A log entry is created for each image in the **Data Table**, including: `fileName`, `originalSize`, `compressedSize`, `imageId`, `outputUrl`, and `processingId`.\n7. When all images are processed, the workflow retrieves the logs for the current `processingId` and generates an HTML report.\n8. A summary email is sent via **Gmail** with processing statistics and total memory saved.\n\n### Setup steps\n- [ ] Create three Google Drive folders: **Input**, **Original Images**, and **Compressed**, then update their folder IDs in the Google Drive nodes.\n- [ ] Create a **Data Table** (e.g. \u201cImage Compression\u201d) with fields: `fileName`, `originalSize`, `compressedSize`, `imageId`, `outputUrl`, `processingId`.\n- [ ] Generate a **TinyPNG/Tinify API key** and add it to the HTTP Basic Auth credentials used by the **Tiny URL API Call** node. - [API Documentation](https://tinypng.com/developers/reference)\n- [ ] Configure your **Gmail** credentials and the recipient address in **Send Report**.\n\n### Customisation\n- Adjust the schedule of the **Daily at 08:00 am** trigger as needed.\n- Update the HTML template in **Generate Report** to add your own branding, logo, footer, or email styling.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5c938d32-7fef-4d8d-8717-bedfae691332",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -288,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 524,
        "height": 524,
        "content": "## 1. Daily trigger to fetch all the pictures to compress and generate a random processing Id"
      },
      "typeVersion": 1
    },
    {
      "id": "bb35f04e-4d62-4796-b775-8b418bd2851f",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 1180,
        "height": 316,
        "content": "## 2. Compress each image using Tinyfy API and log the results"
      },
      "typeVersion": 1
    },
    {
      "id": "5b5b986a-6d11-4bd5-8aea-a6865563f224",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        400
      ],
      "parameters": {
        "color": 7,
        "width": 636,
        "height": 252,
        "content": "## 3. Move the images that have been compressed to the folder for processed images"
      },
      "typeVersion": 1
    },
    {
      "id": "0558053c-9d5e-47cf-9ea2-af868d95165e",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -288,
        656
      ],
      "parameters": {
        "color": 7,
        "width": 1180,
        "height": 188,
        "content": "## 4. Load all logs of the current `processingId` to generate a report sent by email"
      },
      "typeVersion": 1
    },
    {
      "id": "932f6365-26b1-4d1f-89ff-b23fba9f42e2",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        400
      ],
      "parameters": {
        "width": 528,
        "height": 432,
        "content": "## [Video Tutorial](https://youtu.be/qXQVcaJgwrA)\n@[youtube](qXQVcaJgwrA)"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Collect Logs": {
      "main": [
        [
          {
            "node": "Generate Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get all files": {
      "main": [
        [
          {
            "node": "Loop Over Original Files",
            "type": "main",
            "index": 0
          },
          {
            "node": "Loop Over Processed Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Raw Image": {
      "main": [
        [
          {
            "node": "Tiny URL API Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Report": {
      "main": [
        [
          {
            "node": "Send Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Processing Logs": {
      "main": [
        []
      ]
    },
    "Daily at 08:00 am": {
      "main": [
        [
          {
            "node": "Generate Processing Id",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tiny URL API Call": {
      "main": [
        [
          {
            "node": "Download Compressed Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Processing Id": {
      "main": [
        [
          {
            "node": "Get all files",
            "type": "main",
            "index": 0
          },
          {
            "node": "Collect Logs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Original Files": {
      "main": [
        [],
        [
          {
            "node": "Load Raw Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Compressed Image": {
      "main": [
        [
          {
            "node": "Save to Remove Background",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Processed Files": {
      "main": [
        [],
        [
          {
            "node": "Move Files to the Folder /Original",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Remove Background": {
      "main": [
        [
          {
            "node": "Processing Logs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Loop Over Original Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Move Files to the Folder /Original": {
      "main": [
        [
          {
            "node": "Loop Over Processed Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}