DEV Community

Mohamed El-Moumeny
Mohamed El-Moumeny Subscriber

Posted on

Building an AI-Powered Lead Gen Workflow with n8n, Apify, and Gemini

I spent a weekend building a fun proof-of-concept: a fully automated workflow that scrapes leads from Google Maps, uses an AI to score and personalize messages for them, and then saves it all to a spreadsheet.
Here’s a technical breakdown of the stack and the workflow I built in n8n.

A screenshot of an n8n workflow designed for AI-powered lead generation automation. The visual nodes show a process that starts with an Apify HTTP request to scrape data, normalizes it, then uses an AI Agent with the Google Gemini API to personalize emails and score leads. Subsequent nodes handle parsing the AI's JSON output, humanizing the date and time, and finally appending the enriched lead data into a Google Sheet.

The Data Flow

The logic is pretty linear: Scrape -> Normalize -> Enrich with AI -> Parse -> Format -> Store.

  1. Apify for Scraping: The workflow kicks off with an HTTP Request to an Apify actor. Nothing too complex, just a POST request with my search queries in the JSON body. The free tier gave me enough credits to pull a few hundred records for testing.

  2. AI Agent with Gemini: The core of the workflow is the n8n AI Agent node connected to the Google Gemini API. The prompt engineering was key here. I gave it a detailed system prompt defining its role, the input data structure, and—most importantly—the exact JSON format I needed for the output. This included fields for an outreach_score and a communication object with an email and WhatsApp message.

  3. The Gotcha: Parsing AI Output: As many of you know, getting consistently clean JSON from an LLM can be a challenge. The Gemini model would often wrap its valid JSON in a `json markdown block. My first attempts with a simple JSON.parse() failed.

    The fix was an "Edit Fields" node running a bit of JavaScript to clean the string before parsing:
    `javascript
    JSON.parse(rawOutput.replace(/^`
    json\n/, '').replace(/\n`$/, ''))
    `

    A simple solution, but it made the workflow 100x more reliable.

  4. Humanizing the Date: Another small but important transformation. The scrapedAt timestamp was in ISO 8601 format (...Z). I used n8n's built-in Luxon library within an expression to format it for the spreadsheet:
    `javascript
    DateTime.fromISO($json.scrapedAt...).toFormat('dd MMMM yyyy, HH:mm')
    `

    This is way cleaner than handling new Date() objects in a full Code node.

  5. Append to Sheet: The final step is a simple Google Sheets "Append" node that maps the flattened JSON object to the correct columns.

This was a great way to see how powerful the new AI nodes in n8n are. The ability to call an LLM as a simple, integrated step in a workflow, just like any other API, is a total game-changer. Next up, I'll be adding nodes to actually send the outreach.

Anyone else building cool stuff with AI agents in their workflows?

Top comments (0)