AutomationFlowsAI & RAG › Check Japanese Ad Copy Compliance with Google Gemini, Sheets, Slack and Gmail

Check Japanese Ad Copy Compliance with Google Gemini, Sheets, Slack and Gmail

ByOka Hironobu @okp29 on n8n.io

This workflow runs daily to review Japanese ad copy in Google Sheets using Google Gemini, writes compliance risk results back to the sheet, and alerts the right team in Slack (and drafts a Gmail revision request) based on high/medium/low risk. Runs every day at 9:00 on a…

Cron / scheduled trigger★★★★☆ complexityAI-powered20 nodesGoogle SheetsChain LlmGoogle Gemini ChatOutput Parser StructuredSlackGmail
AI & RAG Trigger: Cron / scheduled Nodes: 20 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Chainllm → Gmail 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": "YeRc5dHhphL5l3v0",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Check Japanese ad copy for regulatory risk with Gemini, Sheets and Slack",
  "tags": [],
  "nodes": [
    {
      "id": "36c80240-5f58-42e7-8430-c3133b548be2",
      "name": "Schedule Daily Check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        208,
        96
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "9b62cab5-fc81-4fee-8b85-b9519b938ad9",
      "name": "Get Unchecked Copy",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        432,
        96
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Ad Copy"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "30240466-404c-4ca0-afa1-0c138750d524",
      "name": "Set Review Policy",
      "type": "n8n-nodes-base.set",
      "position": [
        640,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cat",
              "name": "productCategory",
              "type": "string",
              "value": "Health supplement"
            },
            {
              "id": "laws",
              "name": "targetLaws",
              "type": "string",
              "value": "Pharmaceutical and Medical Device Act, Act against Unjustifiable Premiums and Misleading Representations"
            },
            {
              "id": "note",
              "name": "extraRules",
              "type": "string",
              "value": "No guaranteed results, no medical efficacy claims, no unsupported No.1 claims."
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "84280e10-8254-45a0-8445-c4aa1e436959",
      "name": "Check Copy with Gemini",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "onError": "continueErrorOutput",
      "position": [
        912,
        96
      ],
      "parameters": {
        "text": "=You are a Japanese advertising compliance reviewer. Review the marketing copy below against {{ $json.targetLaws }} for a product in the category \"{{ $json.productCategory }}\". Extra rules: {{ $json.extraRules }}\n\nReturn risk_level as high when the copy clearly violates the law, medium when it is risky or ambiguous, low when it is safe. List every problematic phrase with the law it breaches and why, then provide a compliant rewrite in Japanese.\n\nMarketing copy:\n{{ $json.Copy }}",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "87fbd36d-bfcd-4bb9-8243-10cab5dec36e",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        896,
        288
      ],
      "parameters": {
        "options": {
          "temperature": 0.1
        },
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "14bc4cb5-0095-41e1-88c0-52bfac2246e5",
      "name": "Risk Result Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1088,
        288
      ],
      "parameters": {
        "jsonSchemaExample": "{\"risk_level\":\"high\",\"violations\":[{\"phrase\":\"\u5fc5\u305a\u75e9\u305b\u307e\u3059\",\"law\":\"Pharmaceutical and Medical Device Act\",\"reason\":\"Guaranteed medical effect is not allowed\"}],\"safe_rewrite\":\"\u6bce\u65e5\u306e\u98df\u751f\u6d3b\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u307e\u3059\",\"summary\":\"Claims a guaranteed slimming effect\"}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "8823659d-f0e7-469d-bae5-7a2b26a9b003",
      "name": "Parse Risk Result",
      "type": "n8n-nodes-base.code",
      "position": [
        1328,
        80
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const src = $json.output || $json;\nconst row = $('Set Review Policy').item.json;\nconst v = Array.isArray(src.violations) ? src.violations : [];\nconst violations = v.map(function (x) { return (x.phrase || '') + ' [' + (x.law || '') + '] ' + (x.reason || ''); }).join(' | ');\nreturn {\n  copyId: row['Copy ID'] || row.copyId || '',\n  copy: row.Copy || row.copy || '',\n  riskLevel: String(src.risk_level || 'medium').toLowerCase(),\n  violations: violations,\n  violationCount: v.length,\n  safeRewrite: src.safe_rewrite || '',\n  summary: src.summary || ''\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "be15acb1-50b0-4e47-9fb4-8d611874f42a",
      "name": "Update Copy Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1696,
        80
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Ad Copy"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "883a0d76-2586-428a-beef-d28a903b9c38",
      "name": "Route by Risk Level",
      "type": "n8n-nodes-base.switch",
      "position": [
        2048,
        48
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse Risk Result\").item.json.riskLevel }}",
                    "rightValue": "high"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse Risk Result\").item.json.riskLevel }}",
                    "rightValue": "medium"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": false,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $(\"Parse Risk Result\").item.json.riskLevel }}",
                    "rightValue": "low"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Other"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "dafe78f4-c040-4594-b249-c69fdb06a166",
      "name": "Block and Alert Legal",
      "type": "n8n-nodes-base.slack",
      "position": [
        2272,
        32
      ],
      "parameters": {
        "text": "=*:rotating_light: High-risk ad copy blocked*\n*Copy ID:* {{ $(\"Parse Risk Result\").item.json.copyId }}\n*Issues:* {{ $(\"Parse Risk Result\").item.json.violations }}\n*Suggested rewrite:* {{ $(\"Parse Risk Result\").item.json.safeRewrite }}\nDo not publish until legal signs off.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#legal-review"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "9d65b92f-ed9b-496b-9f3a-cee1f9c5144c",
      "name": "Draft Revision Request",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2512,
        32
      ],
      "parameters": {
        "message": "={{ \"Hi,\\n\\nThe following ad copy cannot be published as written:\\n\\n\" + $(\"Parse Risk Result\").item.json.copy + \"\\n\\nIssues found:\\n\" + $(\"Parse Risk Result\").item.json.violations + \"\\n\\nSuggested compliant rewrite:\\n\" + $(\"Parse Risk Result\").item.json.safeRewrite + \"\\n\\nPlease revise and resubmit.\" }}",
        "options": {},
        "subject": "={{ \"Revision required - ad copy \" + $(\"Parse Risk Result\").item.json.copyId }}",
        "resource": "draft"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "74a5cc4f-000d-4681-96d9-4a660adfc16a",
      "name": "Request Marketing Review",
      "type": "n8n-nodes-base.slack",
      "position": [
        2272,
        208
      ],
      "parameters": {
        "text": "=*:eyes: Ad copy needs a second look*\n*Copy ID:* {{ $(\"Parse Risk Result\").item.json.copyId }}\n*Summary:* {{ $(\"Parse Risk Result\").item.json.summary }}\n*Suggested rewrite:* {{ $(\"Parse Risk Result\").item.json.safeRewrite }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#marketing"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "4bed0302-0646-4561-b484-0368a19af57b",
      "name": "Notify Ready to Publish",
      "type": "n8n-nodes-base.slack",
      "position": [
        2272,
        400
      ],
      "parameters": {
        "text": "=*:white_check_mark: Ad copy passed the compliance check*\n*Copy ID:* {{ $(\"Parse Risk Result\").item.json.copyId }}\nReady to publish.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#marketing"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "599e0b62-6a00-4934-bd49-dfa512af0a5f",
      "name": "Flag Unclassified Copy",
      "type": "n8n-nodes-base.slack",
      "position": [
        2272,
        576
      ],
      "parameters": {
        "text": "=*:mag: Compliance result was inconclusive*\n*Copy ID:* {{ $(\"Parse Risk Result\").item.json.copyId }}\nPlease review manually.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#marketing"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "53aac623-b7fe-4829-91ae-bacab7ab3563",
      "name": "Report Check Failure",
      "type": "n8n-nodes-base.slack",
      "position": [
        1328,
        288
      ],
      "parameters": {
        "text": "=*:x: Compliance check failed for copy {{ $(\"Set Review Policy\").item.json[\"Copy ID\"] }}*\nPlease review this copy manually before publishing.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#marketing"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "8701b170-2f36-4c64-898e-c9c56fbf174b",
      "name": "Overview Sticky",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -128
      ],
      "parameters": {
        "width": 568,
        "height": 660,
        "content": "## Check Japanese ad copy for regulatory risk with Gemini, Sheets and Slack\n\n### How it works\nJapanese marketing copy has to comply with the Pharmaceutical and Medical Device Act and the Act against Unjustifiable Premiums and Misleading Representations - a single \"guaranteed results\" phrase can trigger a fine. Each day this template reads unchecked copy from Google Sheets and sends it to a Basic LLM Chain with Google Gemini, which returns a risk level, every problematic phrase with the law it breaches, and a compliant rewrite. The row is updated and marked Checked so nothing is reviewed twice, then a Switch routes by risk: high-risk copy is blocked with a legal alert plus a revision-request email draft, medium goes to marketing review, low is cleared for publishing, and anything unclear is flagged.\n\n### Setup\n1. Connect Google Sheets, Google Gemini (PaLM) API, Gmail and Slack.\n2. Create a sheet with Copy ID, Copy and an empty Status column.\n3. In **Set Review Policy**, set the product category and the rules to enforce.\n\n### Customization tips\nAdd more laws, change the risk bands, or auto-send revision requests."
      },
      "typeVersion": 1
    },
    {
      "id": "f253f70d-05d4-46af-b96f-2f1f1abf916b",
      "name": "S1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 900,
        "content": "## 1. Fetch unchecked copy & configure\nRead only rows without a Status, then set the product category and the rules to enforce."
      },
      "typeVersion": 1
    },
    {
      "id": "05409f16-8fcc-4ba7-aab8-f298fb8f2d58",
      "name": "S2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 712,
        "height": 900,
        "content": "## 2. AI compliance check (Basic LLM Chain)\nGemini returns a risk level, the offending phrases with the law they breach, and a compliant rewrite. Failures are reported to Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "215d361a-6918-4689-9834-270a8ad8c83b",
      "name": "S3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 396,
        "height": 900,
        "content": "## 3. Persist & de-duplicate\nWrite the result back to the row (match on Copy ID) and set Status = Checked so copy is never reviewed twice."
      },
      "typeVersion": 1
    },
    {
      "id": "94aaab81-1cfc-487f-b8a8-e741dcc02576",
      "name": "S4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1968,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 740,
        "height": 900,
        "content": "## 4. Route by risk & act\nHigh blocks with a legal alert and a revision-request draft. Medium goes to marketing review. Low is cleared to publish. Anything else is flagged."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "ab3f4915-e117-4ca1-8570-4e3c627f494c",
  "nodeGroups": [],
  "connections": {
    "Update Copy Row": {
      "main": [
        [
          {
            "node": "Route by Risk Level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Risk Result": {
      "main": [
        [
          {
            "node": "Update Copy Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Review Policy": {
      "main": [
        [
          {
            "node": "Check Copy with Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Unchecked Copy": {
      "main": [
        [
          {
            "node": "Set Review Policy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Risk Result Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Check Copy with Gemini",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Route by Risk Level": {
      "main": [
        [
          {
            "node": "Block and Alert Legal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Request Marketing Review",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Ready to Publish",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Flag Unclassified Copy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Daily Check": {
      "main": [
        [
          {
            "node": "Get Unchecked Copy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Block and Alert Legal": {
      "main": [
        [
          {
            "node": "Draft Revision Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Copy with Gemini": {
      "main": [
        [
          {
            "node": "Parse Risk Result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Check Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Check Copy with Gemini",
            "type": "ai_languageModel",
            "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 workflow runs daily to review Japanese ad copy in Google Sheets using Google Gemini, writes compliance risk results back to the sheet, and alerts the right team in Slack (and drafts a Gmail revision request) based on high/medium/low risk. Runs every day at 9:00 on a…

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

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

This workflow runs weekly to read attendance overtime from Google Sheets, totals it per employee and month, uses Google Gemini to classify risk against Japanese labour-law limits, writes results back

Google Sheets, Chain Llm, Google Gemini Chat +3
AI & RAG

Categories Content Creation AI Automation Publishing Social Media

Google Docs, HTTP Request, Slack +7
AI & RAG

Automate your lead intake, scoring, and outreach pipeline. This workflow collects leads from forms, enriches and scores them using Relevance AI, routes them by quality, and triggers the right follow-u

Form Trigger, HTTP Request, Chain Llm +6
AI & RAG

Automatically identifies overdue sales leads and generates personalized follow-up emails using AI. Runs every weekday Reads leads from Google Sheets Filters leads with no contact for 5+ days Downloads

Google Sheets, Chain Llm, Google Gemini Chat +3
AI & RAG

This workflow monitors Gmail for unread invoice emails with PDF attachments, extracts invoice details with Google Gemini, verifies Japanese qualified invoice registration numbers against the National

Gmail Trigger, Chain Llm, Google Gemini Chat +5