DEV Community

Cover image for How to Build an **ai upsell during customer support** System
Sam Chen
Sam Chen

Posted on Originally published at getaab.com

How to Build an **ai upsell during customer support** System

You can turn every live chat or ticket into a revenue opportunity by wiring a generative-AI model into your support platform, letting it suggest the next best product in real time. The result is a fully automated "AI upsell during customer support" flow that surfaces a personalized offer, sends the customer a checkout link, and logs the conversion back into your CRM - all without the agent having to type a single line.

Below is a step-by-step, production-ready guide that uses Intercom or Zendesk for the support channel, OpenAI for the language model, n8n as the glue, and Shopify (or any Shopify-compatible store) as the fulfillment engine. If you already have a CRM (HubSpot, Salesforce, etc.) you'll see where to plug it in.


What you need

Tool Plan / Price Role
Intercom (or Zendesk) Intercom "Essential" - check the provider's current pricing; Zendesk "Support Team" - check the provider's current pricing Customer-support front-end (chat & ticketing)
OpenAI API Pay-as-you-go; first $18 free credit for new accounts - see the OpenAI pricing page Generates the upsell suggestion
n8n (self-hosted Docker) Free (Community Edition) - run docker run -p 5678:5678 n8nio/n8n Orchestrates webhook → LLM → Shopify
Shopify (Basic) $39/mo (store + API access) - see Shopify pricing page Holds product catalog and creates checkout links
CRM (HubSpot, Salesforce, etc.) Free tier available; paid tiers for advanced automation - check the provider's current pricing Records the upsell event and enriches the contact record
HTTPS endpoint (e.g., ngrok) Free tier for dev; paid for production - check ngrok pricing Exposes n8n webhook to Intercom/Zendesk

Estimated build time: 6-8 hours for a developer familiar with REST APIs and basic workflow tooling.


Step-by-step build

1. Prepare the support platform webhook

Both Intercom and Zendesk can push a payload whenever a conversation is updated.

  • Intercom: In the Intercom UI go to Settings → App → Webhooks and create a new webhook. Set the Event to conversation.user.replied and point it at https://your-n8n-host.com/webhook/ai-upsell. Leave the default "Send full payload".

  • Zendesk: Navigate to Admin → Extensions → Target URLsAdd target. Choose HTTP Target, give it a name like AI Upsell, paste the same n8n URL, and select POST JSON. Then create a Trigger under Admin → Business Rules → Triggers: when Ticket is Updated AND Assignee is not empty, fire the target.

"A webhook that fires on every reply guarantees you never miss an upsell opportunity."

Make sure the endpoint is reachable from the internet. For local testing you can spin up ngrok http 5678 and copy the generated https URL into the webhook config.

2. Spin up n8n (self-hosted)

docker run -d \
 --name n8n \
 -p 5678:5678 \
 -e N8N_BASIC_AUTH_ACTIVE=true \
 -e N8N_BASIC_AUTH_USER=admin \
 -e N8N_BASIC_AUTH_PASSWORD=changeme123 \
 n8nio/n8n
Enter fullscreen mode Exit fullscreen mode
  • The command runs n8n on port 5678 with basic auth. Replace changeme123 with a strong password.
  • Open https://your-host:5678 in a browser, log in, and you're ready to build the workflow.

3. Create the AI Upsell workflow

  1. Webhook node - set HTTP Method to POST, Path to /webhook/ai-upsell. This is the entry point that receives the conversation payload.

  2. Set node (Extract relevant data) - map the incoming JSON to a clean object:

    • customerId{{ $json["user"]["id"] }} (Intercom) or {{ $json["ticket"]["requester_id"] }} (Zendesk)
    • latestMessage{{ $json["conversation"]["conversation_message"]["body"] }} (Intercom) or {{ $json["ticket"]["description"] }} (Zendesk)
    • email{{ $json["user"]["email"] }} or {{ $json["ticket"]["requester"]["email"] }}
  3. HTTP Request node (OpenAI Completion) - configure as follows:

{
 "url": "https://api.openai.com/v1/chat/completions",
 "method": "POST",
 "headers": {
 "Content-Type": "application/json",
 "Authorization": "Bearer {{ $env.OPENAI_API_KEY }}"
 },
 "body": {
 "model": "gpt-4o-mini",
 "messages": [
 {
 "role": "system",
 "content": "You are a sales assistant for an e-commerce store. Suggest one relevant product upgrade based on the customer's last message. Keep the tone friendly and concise (max 50 words). Return only JSON: {\"product_id\":\"...\",\"reason\":\"...\"}."
 },
 {
 "role": "user",
 "content": "{{ $json[\"latestMessage\"] }}"
 }
 ],
 "temperature": 0.3,
 "max_tokens": 150
 }
}
Enter fullscreen mode Exit fullscreen mode
  • What this does: Calls OpenAI's chat endpoint with a system prompt that forces a short JSON response containing the recommended product_id and a brief reason.
  1. Function node (Parse OpenAI response) - add a simple JavaScript snippet:
items[0].json = JSON.parse($json["choices"][0]["message"]["content"]);
return items;
Enter fullscreen mode Exit fullscreen mode
  • This extracts the JSON produced by the LLM into item.json.product_id and item.json.reason.
  1. HTTP Request node (Shopify Checkout Link) - create a checkout URL for the suggested product:
{
 "url": "https://{{ $env.SHOPIFY_STORE }}/api/2023-10/checkouts.json",
 "method": "POST",
 "authentication": "basicAuth",
 "user": "{{ $env.SHOPIFY_API_KEY }}",
 "password": "{{ $env.SHOPIFY_PASSWORD }}",
 "body": {
 "checkout": {
 "line_items": [
 {
 "variant_id": "{{ $json[\"product_id\"] }}",
 "quantity": 1
 }
 ],
 "email": "{{ $json[\"email\"] }}"
 }
 }
}
Enter fullscreen mode Exit fullscreen mode
  • What this does: Calls Shopify's checkout API and returns a checkout_url that the customer can click to complete the upsell purchase.
  1. IF node (Eligibility filter) - prevent upsell in low-value or support-only tickets. For example, only proceed if the latest message contains keywords like "upgrade", "more", "extra". Use a simple expression:
{{ $json["latestMessage"].toLowerCase().includes("upgrade") || $json["latestMessage"].toLowerCase().includes("extra") }}
Enter fullscreen mode Exit fullscreen mode
  1. Send Message back to Support Platform
  • For Intercom, add an HTTP Request node targeting https://api.intercom.io/messages with the Authorization: Bearer <INTERCOM_TOKEN> header and a body:
 {
 "message_type": "inapp",
 "body": "Hey! Based on what you said, I think you'll love our {{ $json[\"reason\"] }}. 👉 {{ $json[\"checkout_url\"] }}",
 "from": { "type": "admin", "id": "<ADMIN_ID>" },
 "to": { "type": "user", "id": "{{ $json[\"customerId\"] }}" }
 }
Enter fullscreen mode Exit fullscreen mode
  • For Zendesk, use the Create Ticket endpoint https://yourdomain.zendesk.com/api/v2/tickets.json with a body that adds a public comment containing the upsell line.
  1. CRM Update (optional) - add a HTTP Request node pointing at your CRM's "Create Deal" endpoint. Include customerId, product_id, and a flag upsell_generated: true.

  2. Save & Activate - turn the workflow on. Test by sending a fake message through Intercom/Zendesk that contains "I want something bigger". You should see the AI suggest a product, n8n hit Shopify, and the support UI reply with a checkout link.

4. Secure your secrets

Create an .env file in the n8n Docker container (or set environment variables in your host) with:

OPENAI_API_KEY=sk-...
INTERCOM_TOKEN=...
SHOPIFY_STORE=yourstore.myshopify.com
SHOPIFY_API_KEY=...
SHOPIFY_PASSWORD=...
Enter fullscreen mode Exit fullscreen mode

Restart the container so n8n picks up the new vars:

docker restart n8n
Enter fullscreen mode Exit fullscreen mode

5. Monitoring and logging

  • In n8n, enable Execution Logging (under Settings → Execution). Set the retention to 30 days.
  • For production, forward logs to a log aggregation service (e.g., Papertrail) by adding a docker run -e LOGGING_PROVIDER=papertrail ... flag.

Where this breaks

"The weakest link is always the webhook latency; a 5-second delay can make the suggestion feel out-of-sync."

Failure point Symptom Fix
Webhook auth mismatch Intercom/Zendesk reports "401 Unauthorized" Verify the token values in your .env and that the header name matches the platform's docs (Authorization: Bearer ... for Intercom, Authorization: Basic ... for Zendesk).
OpenAI rate limits HTTP 429 response from api.openai.com Upgrade to a higher quota or implement exponential back-off. Cache recent product_id suggestions for identical messages to reduce calls.
Shopify checkout API version deprecation 404 on /api/2023-10/checkouts.json Pin the API version in the URL (/api/2024-01/...) and monitor Shopify's deprecation schedule.
n8n execution timeout (default 30 s) Workflow stops before the checkout link is created Increase the timeout under Settings → Workflow or split the flow into two webhooks (one for AI, one for Shopify).
Eligibility filter too strict No upsell ever sent even when relevant Tune the keyword list or switch to a small text-classification model (e.g., OpenAI's text-classification endpoint) to detect intent more reliably.
Cost runaway Monthly OpenAI bill spikes Add a per-day quota node that caps the number of completions (e.g., 500 calls/day). Track usage with n8n's built-in "Workflow Execution" metrics.

For a deeper technical reference, see n8n's documentation.

FAQ

How does the AI know which product to suggest?

The system prompt tells the model to "pick the most relevant product from our catalog". You can make it smarter by passing a few-shot example list of product IDs and descriptions in the prompt, or by enriching the prompt with the customer's purchase history fetched from your CRM before the OpenAI call.

Can I use a different e-commerce platform than Shopify?

Yes. Replace the Shopify checkout node with the equivalent API call for WooCommerce, BigCommerce, or a custom cart service. The only requirement is that the endpoint returns a URL that you can embed in the support reply.

What if the customer replies after the upsell suggestion?

Treat the conversation as a new event. The webhook fires again, the AI receives the latest message, and the eligibility filter decides whether to propose another upsell. You can also add a flag in the CRM (last_upsell_timestamp) to enforce a minimum gap (e.g., 48 hours) between suggestions.

Is it safe to expose the checkout link in a support chat?

Shopify's checkout URLs are single-use and tied to the email you pass in the payload, so they can't be hijacked easily. Nevertheless, enable HTTPS everywhere and never expose your API keys in the front-end. All secret handling stays inside n8n.

Do I need to train a custom model?

Not for most small-to-medium stores. The gpt-4o-mini model with a well-crafted system prompt yields accurate suggestions for a catalog of up to a few thousand SKUs. If you have >10 k products, consider adding a lookup step that selects the top-10 candidates by tag before sending the list to the LLM.

Where can I find more ready-made ideas?

Check out the AI automations you can sell page for a catalog of plug-and-play workflows, or grab the free guide at https://getaab.com/free to get template n8n JSON files you can import instantly.


By wiring together a support platform, OpenAI, n8n, and Shopify you get a scalable ai upsell during customer support engine that works on every ticket, respects the agent's workflow, and captures the extra revenue in your CRM. The pieces are all real-world products with documented APIs, so you can replicate the flow today, iterate on the prompts, and watch your average order value climb. Happy building.

Related reading

Top comments (0)