AutomationFlowsAI & RAG › Send Post-purchase Email Sequences with Postgres, Gmail and Openai

Send Post-purchase Email Sequences with Postgres, Gmail and Openai

ByAvkash Kakdiya @itechnotion on n8n.io

This workflow automates customer communication after an order is placed. It detects new orders, sends a confirmation email, waits until delivery is completed, and then follows up with AI-generated product tips. Finally, it sends AI-powered upsell recommendations after a defined…

Cron / scheduled trigger★★★★☆ complexityAI-powered19 nodesGmailPostgresOpenAI
AI & RAG Trigger: Cron / scheduled Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Gmail → OpenAI 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
{
  "nodes": [
    {
      "id": "e7a7d230-8eb4-45b8-8cc4-4756af647e3d",
      "name": "Wait until product get deliver",
      "type": "n8n-nodes-base.wait",
      "position": [
        -448,
        2832
      ],
      "parameters": {
        "unit": "days",
        "amount": 7
      },
      "typeVersion": 1.1
    },
    {
      "id": "adea234b-a3ec-4389-a447-aae6f0da6f4c",
      "name": "Wait for 2 weeks",
      "type": "n8n-nodes-base.wait",
      "position": [
        992,
        2752
      ],
      "parameters": {
        "unit": "days",
        "amount": 14
      },
      "typeVersion": 1.1
    },
    {
      "id": "ee34d1d3-8db9-4c38-a247-8643da4a8c6f",
      "name": "Order Placed Ack.",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -656,
        2832
      ],
      "parameters": {
        "sendTo": "={{ $json.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n<body style=\"margin:0; padding:0; background-color:#f9f9f9; font-family:Arial, sans-serif;\">\n\n  <div style=\"max-width:600px; margin:30px auto; background:#ffffff; padding:24px; border-radius:8px;\">\n    \n    <h2 style=\"color:#333;\">Your Order Is Confirmed</h2>\n\n    <p>Hi <strong>{{ $json.client_name }}</strong>,</p>\n\n    <p>\n      Thank you for your purchase!  \n      We\u2019re happy to let you know that your order for\n      <strong>{{ $json.product_name }}</strong> has been successfully placed.\n    </p>\n\n    <p style=\"margin:16px 0;\">\n      <strong>Estimated Delivery Date:</strong> {{ $json.estimated_delivery_date.split('T')[0] }}\n\n    </p>\n\n    <p>\n      We\u2019ll notify you once your order is on the way.\n    </p>\n\n    <p>\n      If you have any questions, just reply to this email \u2014 we\u2019re here to help!\n    </p>\n\n    <p style=\"margin-top:32px;\">\n      Best regards,<br>\n      <strong>Customer Support Team</strong>\n    </p>\n\n  </div>\n\n</body>\n</html>\n",
        "options": {},
        "subject": "Your Order Is Confirmed "
      },
      "typeVersion": 2.2
    },
    {
      "id": "8947ca5e-3169-4f57-a612-202237dd6f4c",
      "name": "Send Tips to User",
      "type": "n8n-nodes-base.gmail",
      "position": [
        816,
        2752
      ],
      "parameters": {
        "sendTo": "={{ $('Execute a SQL query').item.json.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n  <body style=\"margin:0; padding:0; background-color:#f6f6f6; font-family:Arial, sans-serif;\">\n\n    <div style=\"max-width:600px; margin:24px auto; background:#ffffff; padding:24px; border-radius:8px;\">\n\n      <h2 style=\"margin-top:0; color:#222;\">\n        Get the Best Out of Your {{ $('Execute a SQL query').item.json.product_name }}\n      </h2>\n\n      <p style=\"color:#333;\">\n        Hi <strong>Devansh</strong>,\n      </p>\n      <p style=\"color:#333;\">\n        Here are a few practical tips to help you get the most out of your\n        <strong>{{ $('Execute a SQL query').item.json.product_name }}</strong>:\n      </p>\n\n      <!-- IMPORTANT: NO <p> HERE -->\n      <div style=\"margin:16px 0; color:#333;\">\n        {{$json.formattedOutput}}\n      </div>\n\n      <p style=\"color:#333;\">\n        If you have any questions, just reply to this email \u2014 we\u2019re happy to help.\n      </p>\n\n      <p style=\"margin-top:24px; color:#333;\">\n        Best regards,<br>\n        <strong>Customer Success Team</strong>\n      </p>\n\n    </div>\n\n  </body>\n</html>\n",
        "options": {},
        "subject": "=Getting Started with Your {{ $('Execute a SQL query').item.json.product_name }}"
      },
      "typeVersion": 2.2
    },
    {
      "id": "06d92300-d3bc-4dd7-a492-685ee0b8db77",
      "name": "Send Tips to User1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1664,
        2752
      ],
      "parameters": {
        "sendTo": "={{ $('Execute a SQL query').item.json.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n<body style=\"margin:0; padding:0; background-color:#f9f9f9; font-family:Arial, sans-serif;\">\n\n  <div style=\"max-width:600px; margin:30px auto; background:#ffffff; padding:24px; border-radius:8px;\">\n\n    <h2 style=\"color:#333;\">A Perfect Match for Your {{ $('Execute a SQL query').item.json.product_name }}</h2>\n\n    <p>Hi <strong>{{ $('Execute a SQL query').item.json.client_name }}</strong>,</p>\n\n    <p>\n      We hope you\u2019ve been loving your <strong>{{ $('Execute a SQL query').item.json.product_name }}</strong>! \n    </p>\n\n    <p>\n      Based on your purchase, we thought you might find this helpful:\n    </p>\n\n    <div style=\"background:#f2f2f2; padding:16px; border-radius:6px; margin:16px 0;\">\n      {{$json.formattedOutput}}\n    </div>\n\n    <p>\n      Many customers use this together with your current product to get even better results.\n    </p>\n\n    <p>\n      If you\u2019d like to know more, just reply to this email \u2014 we\u2019d be happy to help!\n    </p>\n\n    <p style=\"margin-top:32px;\">\n      Warm regards,<br>\n      <strong>Product Recommendations Team</strong>\n    </p>\n\n  </div>\n\n</body>\n</html>\n",
        "options": {},
        "subject": "=You Might Love This with Your {{ $('Execute a SQL query').item.json.product_name }}\n"
      },
      "typeVersion": 2.2
    },
    {
      "id": "823df403-fb23-4ec1-bae5-014a17fd9b3e",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1040,
        2832
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 2
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "9d16a835-0279-4404-93ae-def9a202fb28",
      "name": "Execute a SQL query",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -848,
        2832
      ],
      "parameters": {
        "query": "SELECT *\nFROM orders\nWHERE created_at >= NOW() - INTERVAL '2 minute'\nORDER BY created_at ASC;\n",
        "options": {},
        "operation": "executeQuery"
      },
      "typeVersion": 2.6
    },
    {
      "id": "690aca95-d69a-4e96-89fb-68c92da121a1",
      "name": "Select rows from a table",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -256,
        2832
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "orders",
          "cachedResultName": "orders"
        },
        "where": {
          "values": [
            {
              "value": "={{ $('Execute a SQL query').item.json.order_id }}",
              "column": "order_id"
            }
          ]
        },
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "options": {},
        "operation": "select"
      },
      "typeVersion": 2.6
    },
    {
      "id": "3cd9eb5f-0f9f-4946-a996-d7a54fc34f51",
      "name": "Wait for a day",
      "type": "n8n-nodes-base.wait",
      "position": [
        112,
        2928
      ],
      "parameters": {
        "unit": "days",
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "b860995e-3e7c-43d8-b7f6-5df2dcf674e9",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -496,
        2512
      ],
      "parameters": {
        "color": 7,
        "width": 768,
        "height": 752,
        "content": "## Step 2 \u2014 Delivery Status Check\nWaits for delivery and rechecks order status until delivered.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a0bd7ba6-5a92-4ce2-a51a-d147e6c19303",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        2512
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 752,
        "content": "## Step 3 \u2014 Product Usage Tips (AI)\nGenerates and emails AI-based usage tips after delivery.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b3a36d91-de29-4e23-9046-ce4b5e7bf291",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        2512
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 752,
        "content": "## Step 4 \u2014 Upsell Recommendations (AI)\nWaits two weeks and sends AI-generated complementary product suggestions.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1591c534-c64c-413b-bb5d-a91745e1d9d0",
      "name": "Step -1 Trigger & Order Detection",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1088,
        2512
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 752,
        "content": "## Step 1 \u2014 Order Detection & Confirmation\nFetches new orders and sends an order confirmation email to the customer.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "aad79404-5b69-473f-95ca-d6c410788a39",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        2512
      ],
      "parameters": {
        "width": 576,
        "height": 752,
        "content": "## Order Placed \u2192 Delivery-Based Upsell Automation\n\nThis workflow automates post-purchase customer engagement using email and AI. It confirms new orders, waits for delivery, sends helpful product usage tips, and later follows up with personalized upsell recommendations to increase repeat purchases and customer satisfaction.\n\n### How it works\nThe workflow starts on a scheduled trigger and checks for newly created orders in the database. When a new order is found, a confirmation email is immediately sent to the customer.\n\nAfter confirmation, the workflow waits until the expected delivery time and rechecks the order status. If the product has not been delivered yet, it waits one more day and checks again. This loop continues until the order is marked as delivered.\n\nOnce delivery is confirmed, the product details are sent to an AI agent that generates short, practical usage tips. These tips are formatted and emailed to the customer.\n\nAfter the tips are sent, the workflow waits for two weeks. It then uses AI again to generate complementary product recommendations based on the original purchase and sends them as an upsell email.\n\n### Setup steps\n1. Connect your Postgres database with order and delivery fields  \n2. Configure Gmail or SMTP credentials  \n3. Verify the delivery status field logic  \n4. Add AI model credentials and review prompts  \n5. Adjust wait durations if needed  \n6. Activate and test with a sample order\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7bb156f5-ed86-49f5-9512-38d552a41f98",
      "name": "Format AI response3",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        2752
      ],
      "parameters": {
        "jsCode": "return $input.all().map(item => {\n  const original = item.json;\n\n  const text = original.output || \"\";\n\n  // Split by \"* \" and clean items\n  const items = text\n    .split(\"* \")\n    .map(i => i.trim())\n    .filter(i => i.length > 0);\n\n  // Build proper HTML list\n  const html =\n    \"<ul style='padding-left:20px; margin:0;'>\" +\n    items.map(i => `<li>${i}</li>`).join(\"\") +\n    \"</ul>\";\n\n  // IMPORTANT: merge old data + new field\n  return {\n    json: {\n      ...original,\n      formattedOutput: html\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8ba50f01-d769-4f65-ba3f-e23ee07c90b1",
      "name": "Code in JavaScript1",
      "type": "n8n-nodes-base.code",
      "position": [
        1472,
        2752
      ],
      "parameters": {
        "jsCode": "return $input.all().map(item => {\n  const original = item.json;\n\n  const rawText = original.output || \"\";\n\n  // Split on \"* \" bullet\n  const items = rawText\n    .split('* ')\n    .map(i => i.trim())\n    .filter(i => i.length > 0);\n\n  // Convert to HTML list\n  const listItems = items.map(i => `<li>${i}</li>`).join('');\n\n  return {\n    json: {\n      ...original, // \ud83d\udc48 preserve email, product_name, etc.\n      formattedOutput: `<ul style=\"padding-left:20px; margin:0;\">${listItems}</ul>`\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f2e95170-467e-43b7-86b3-5b443b67f789",
      "name": "If2",
      "type": "n8n-nodes-base.if",
      "position": [
        -80,
        2832
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0c24df6c-7ff0-4612-8076-7877b8eee733",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.delivered }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "dffda946-f2d4-440b-b401-d2ae9013a203",
      "name": "Message a model",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        336,
        2752
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=You are a customer onboarding assistant.\nYour job is to write concise product usage tips for email.\nFollow these rules strictly:\nDo NOT add any introduction or closing sentence\nDo NOT start with phrases like \"Here is\", \"Here are\", or similar\nMaximum 5 bullet points\nUse \"*\" buttet only\nEach bullet must be one short sentence\nFriendly, clear, and simple tone\nNo emojis\nNo markdown headings\nNo new line chars\nAnd Product is : {{ $('Execute a SQL query').item.json.product_name }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "2c54f67f-4f7e-4cd8-8647-9079007a1ce9",
      "name": "Message a model1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1184,
        2752
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=You are a customer onboarding assistant.\nYour job is to write concise product usage tips for email.\nFollow these rules strictly:\nDo NOT add any introduction or closing sentence\nDo NOT start with phrases like \"Here is\", \"Here are\", or similar\nMaximum 5 bullet points\nUse \"*\" buttet only\nEach bullet must be one short sentence\nFriendly, clear, and simple tone\nNo emojis\nNo markdown headings\nNo new line chars\nAnd Product is : {{ $('Execute a SQL query').item.json.product_name }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "connections": {
    "If2": {
      "main": [
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for a day",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for a day": {
      "main": [
        [
          {
            "node": "Select rows from a table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model": {
      "main": [
        [
          {
            "node": "Format AI response3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model1": {
      "main": [
        [
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Execute a SQL query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for 2 weeks": {
      "main": [
        [
          {
            "node": "Message a model1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Order Placed Ack.": {
      "main": [
        [
          {
            "node": "Wait until product get deliver",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Tips to User": {
      "main": [
        [
          {
            "node": "Wait for 2 weeks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript1": {
      "main": [
        [
          {
            "node": "Send Tips to User1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute a SQL query": {
      "main": [
        [
          {
            "node": "Order Placed Ack.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format AI response3": {
      "main": [
        [
          {
            "node": "Send Tips to User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select rows from a table": {
      "main": [
        [
          {
            "node": "If2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait until product get deliver": {
      "main": [
        [
          {
            "node": "Select rows from a table",
            "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 workflow automates customer communication after an order is placed. It detects new orders, sends a confirmation email, waits until delivery is completed, and then follows up with AI-generated product tips. Finally, it sends AI-powered upsell recommendations after a defined…

Source: https://n8n.io/workflows/13274/ — 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

A scheduled process aggregates content from eight distinct data sources and standardizes all inputs into a unified format. AI models perform sentiment scoring, detect conspiracy or misinformation sign

HTTP Request, OpenAI, Postgres +2
AI & RAG

Personalized Outreach & Follow-Up - Phase 2. Uses googleSheets, openAi, gmail, gmailTrigger. Scheduled trigger; 59 nodes.

Google Sheets, OpenAI, Gmail +2
AI & RAG

User Signup & Verification: The workflow starts when a user signs up. It generates a verification code and sends it via SMS using Twilio. Code Validation: The user replies with the code. The workflow

Postgres, HTTP Request, OpenAI +2
AI & RAG

This workflow monitors filesystem sync and backup jobs by validating their execution logs, not by running or inspecting the jobs themselves.

Google Cloud Storage, Gmail, GitHub +2
AI & RAG

This advanced workflow automates brand monitoring and media coverage tracking for musicians, bands, and music labels. The system uses multiple search queries (dorky) to discover mentions across the we

Google Sheets, Gmail, @Brave/N8N Nodes Brave Search +1