Queue-North-Website/docs/zoho-setup.md

6.2 KiB
Raw Blame History

Zoho CRM Setup Guide for Queue North Admins

This guide walks you through the current Zoho CRM integration. Contact leads use the legacy Zoho WebToLead form tokens, while the OAuth/API integration remains available as a standby option for future lead upserts or support cases.


Prerequisites

Before you begin, ensure you have:

  • A Zoho CRM account (admin access required)
  • The WebToLead hidden field values from the old Zoho form

Step 1: Gather WebToLead Values

The current integration needs the old Zoho form's hidden fields:

xnQsjsdp
xmIwtLD
actionType
returnURL
zc_gad

These values are stored locally in zoho.md, which is ignored by git.


Optional Standby: Create a Zoho Self-Client App

Only use these OAuth steps if switching ZOHO_FORWARDING_MODE=api.

  1. Go to https://api-console.zoho.com
  2. Click "Create Self Client"
  3. Fill in:
    • Client Name: Queue-North-Zoho-Integration
    • Description: Auto-capture leads and cases from Queue North website
    • Redirect URI: https://www.zoho.com (required for Self-Client, not used)
  4. Click Create
  5. Copy and save:
    • Client ID
    • Client Secret

⚠️ Store these securely — they're like a username and password.


Optional Standby: Generate an Authorization Code

  1. In the Self Client tab, click "Generate Code"
  2. Set the Scope to:
    ZohoCRM.modules.leads.CREATE,ZohoCRM.modules.leads.READ,ZohoCRM.modules.cases.CREATE,ZohoCRM.modules.cases.READ
    
  3. Set Expiry to 10 minutes (use it quickly)
  4. Click Generate
  5. Copy the authorization code — it expires in 10 minutes

Optional Standby: Exchange Auth Code for Tokens

Run this curl command (replace placeholders):

curl -X POST https://accounts.zoho.com/oauth/v2/token \
  -d "code=<YOUR_AUTH_CODE>" \
  -d "client_id=<YOUR_CLIENT_ID>" \
  -d "client_secret=<YOUR_CLIENT_SECRET>" \
  -d "grant_type=authorization_code" \
  -d "redirect_uri=https://www.zoho.com"

Response will include:

{
  "access_token": "1000.xxxxx.xxxxx",
  "refresh_token": "1000.yyyyy.yyyyy",
  "expires_in": 3600,
  "token_type": "bearer"
}

Save the refresh_token — this never expires and must be kept secret.


Step 2: Configure Environment Variables

The current production-friendly setup uses the legacy Zoho WebToLead form tokens for contact leads while keeping the OAuth API integration available as a standby option.

Add these to your .env file for WebToLead lead forwarding:

ZOHO_FORWARDING_MODE=webtolead
ZOHO_WEBTOLEAD_ENABLED=true
ZOHO_WEBTOLEAD_URL=https://crm.zoho.com/crm/WebToLeadForm
ZOHO_WEBTOLEAD_XNQSJSDP=<from Zoho WebToLead hidden field>
ZOHO_WEBTOLEAD_XMIWTLD=<from Zoho WebToLead hidden field>
ZOHO_WEBTOLEAD_ACTION_TYPE=TGVhZHM=
ZOHO_WEBTOLEAD_RETURN_URL=null
ZOHO_WEBTOLEAD_ZC_GAD=

Use these only if switching back to the Zoho CRM REST API/OAuth integration:

ZOHO_FORWARDING_MODE=api
ZOHO_ENABLED=false
ZOHO_API_DOMAIN=https://www.zohoapis.com
ZOHO_ACCOUNTS_DOMAIN=https://accounts.zoho.com
ZOHO_CLIENT_ID=<from Step 1>
ZOHO_CLIENT_SECRET=<from Step 1>
ZOHO_REFRESH_TOKEN=<from Step 3>
# Cases forwarding is also OFF by default
ZOHO_CASES_ENABLED=false

Note: ZOHO_CASES_ENABLED only applies to the OAuth/API path. The WebToLead values found in the old site are for lead capture only.

Datacenter Variants

If your Zoho datacenter is outside the US, adjust the domains:

Region API Domain Accounts Domain
US www.zohoapis.com accounts.zoho.com
EU www.zohoapis.eu accounts.zoho.eu
IN www.zohoapis.in accounts.zoho.in
AU www.zohoapis.com.au accounts.zoho.com.au

Step 3: Test the Integration

Test Lead Capture

  1. Submit a lead on the contact form (name, email, phone, message)
  2. Wait ~510 seconds
  3. Log in to Zoho CRM → Leads tab
  4. Verify the new lead appears with correct data

Test Case Capture

  1. Submit a support request (e.g., booking inquiry, technical question)
  2. Wait ~510 seconds
  3. Log in to Zoho CRM → Cases tab
  4. Verify the new case appears with correct data

Troubleshooting

Token Errors

  • "invalid_grant": Your authorization code expired. Generate a new one in Step 2 and repeat Step 3.
  • "invalid_client": Double-check Client ID and Secret — no extra spaces.
  • "invalid_scope": Re-run Step 2 with the exact scopes listed above.

Field Mismatches

  • If leads/cases don't appear, check if Zoho requires custom fields like Service_Interest
  • Edit the field mapping in server/zoho/ to match your Zoho CRM field API names

Cases Not Appearing

  • Ensure ZOHO_CASES_ENABLED=true is set
  • Verify the Cases tab is enabled in your Zoho CRM plan
  • Check that your Zoho CRM user has Cases CREATE permissions

Lead Upsert Behavior

  • Leads are upserted by email: duplicate email = update existing lead
  • Cases are always inserted (new ticket each time)
  • If you see duplicate leads, check for slight email variations (e.g., test@ vs test+1@)

Architecture Notes

Flow Overview

Website Contact Form → SQLite (always saved)
                        ↓
                 Zoho CRM (best-effort)
                        ↓
                 Fire-and-forget (no failure blocking)

OAuth2 Refresh Token Flow

  1. Use refresh_token to get a new access_token when expired
  2. access_token expires in 1 hour
  3. refresh_token never expires — store it securely

Upsert Logic

  • Leads: WebToLead creates leads through the legacy Zoho form endpoint. API mode uses email-based upsert.
  • Cases: Always insert (new case per submission)

Fire-and-Forget Design

  • Zoho failures do not block form submissions
  • All data is saved to SQLite first
  • Zoho attempts happen in the background
  • No retry logic needed — users won't wait for Zoho

What Happens Next?

After configuration:

  1. Deploy the environment variables to production
  2. Set ZOHO_WEBTOLEAD_ENABLED=true in production .env
  3. Restart the application
  4. Submit a test lead and support case to verify data flows to Zoho CRM
  5. Check Zoho CRM Leads and Cases tabs to confirm both appear

Need help? Contact your site administrator.