Overview

This guide shows you how to integrate SpiderIQ’s orchestrated campaigns with Xano, a no-code backend platform. You’ll build a complete lead generation system that:
  1. Creates orchestrated campaigns via SpiderIQ API
  2. Processes locations automatically with workflow chaining
  3. Stores enriched leads in your Xano database
  4. Schedules recurring campaigns with Xano Tasks

Prerequisites

Xano Account

Free tier works for testing. Pro tier recommended for production.

SpiderIQ Credentials

Your API token from SpiderIQ dashboard.

Step 1: Store API Credentials

First, securely store your SpiderIQ API token in Xano’s environment variables.
1

Open Xano Settings

Navigate to your Xano workspace → Settings → Environment Variables
2

Add SpiderIQ Token

Create a new variable:
  • Name: SPIDERIQ_TOKEN
  • Value: Your SpiderIQ API token (e.g., cli_xxx:sk_xxx:secret_xxx)
  • Environment: Production (and optionally Development)
3

Save Changes

Click Save. This token is now accessible in all Function Stacks.
Never hardcode API tokens in Function Stacks. Always use environment variables for security.

Step 2: Create Database Tables

Create three tables to store campaign data and leads.

Table: campaigns

FieldTypeDescription
idInteger (Auto)Primary key
campaign_idTextSpiderIQ campaign ID
queryTextSearch query (e.g., “restaurants”)
country_codeTextISO country code
statusTextCampaign status
total_locationsIntegerNumber of locations
has_workflowBooleanWorkflow enabled
created_atTimestampCreation time
completed_atTimestampCompletion time

Table: leads

FieldTypeDescription
idInteger (Auto)Primary key
campaign_idTextForeign key to campaigns
business_nameTextBusiness name
business_addressTextFull address
business_phoneTextPhone number
business_ratingDecimalGoogle rating
domainTextWebsite domain
locationTextCity/location name
workflow_stageTextCurrent stage
created_atTimestampCreation time

Table: lead_emails

FieldTypeDescription
idInteger (Auto)Primary key
lead_idIntegerForeign key to leads
emailTextEmail address
statusTextvalid, invalid, risky, unknown
scoreIntegerDeliverability score (0-100)
is_deliverableBooleanIs deliverable
is_role_accountBooleanIs role account (info@, etc.)
Add indexes on campaign_id fields for better query performance when processing large campaigns.

Step 3: Create Campaign Function Stack

Build a Function Stack to create orchestrated campaigns.

Function Stack: create_campaign

Input Parameters:
  • query (Text, required) - Search query
  • country_code (Text, required) - ISO country code
  • min_population (Integer, optional) - Minimum city population
Node 1: Build Request Body
  • Type: Create Variable
  • Name: request_body
  • Value (Object):
{
  "query": "$input.query",
  "country_code": "$input.country_code",
  "filter": {
    "mode": "population",
    "min_population": "$input.min_population"
  },
  "workflow": {
    "spidersite": {
      "enabled": true,
      "max_pages": 10,
      "extract_company_info": true
    },
    "spiderverify": {
      "enabled": true,
      "max_emails_per_business": 5
    },
    "filter_social_media": true,
    "filter_review_sites": true
  }
}
Node 2: HTTP Request
  • Type: External API Request
  • Method: POST
  • URL: https://spideriq.di-atomic.com/api/v1/jobs/spiderMaps/campaigns/submit
  • Headers:
    • Authorization: Bearer $env.SPIDERIQ_TOKEN
    • Content-Type: application/json
  • Body: $var.request_body
Node 3: Store Campaign
  • Type: Add Record (campaigns table)
  • Fields:
    • campaign_id: $external.campaign_id
    • query: $input.query
    • country_code: $input.country_code
    • status: $external.status
    • total_locations: $external.total_locations
    • has_workflow: $external.has_workflow
    • created_at: now()
Node 4: Return Response
  • Type: Return
  • Value: $external (full SpiderIQ response)

Example Response

{
  "campaign_id": "camp_fr_restaurants_20251223_abc123",
  "status": "active",
  "total_locations": 42,
  "has_workflow": true
}

Step 4: Process Campaign Loop

Create a Function Stack that processes all locations in a campaign.

Function Stack: process_campaign

Input Parameters:
  • campaign_id (Text, required) - The SpiderIQ campaign ID
Node 1: Initialize Loop Variable
  • Type: Create Variable
  • Name: has_more
  • Value: true
Node 2: While Loop
  • Type: Loop (While)
  • Condition: $var.has_more == true
Inside Loop:Node 2.1: Call /next Endpoint
  • Type: External API Request
  • Method: POST
  • URL: https://spideriq.di-atomic.com/api/v1/jobs/spiderMaps/campaigns/$input.campaign_id/next
  • Headers:
    • Authorization: Bearer $env.SPIDERIQ_TOKEN
Node 2.2: Update has_more
  • Type: Update Variable
  • Name: has_more
  • Value: $external.has_more
Node 2.3: Conditional (if current_task exists)
  • Type: Conditional
  • Condition: $external.current_task != null
Node 2.3.1: Log Progress (inside conditional)
  • Type: Create Variable
  • Name: progress_log
  • Value: Processing: $external.current_task.search_string
Node 2.4: Wait (Rate Limiting)
  • Type: Utilities → Wait
  • Duration: 2 seconds
End LoopNode 3: Update Campaign Status
  • Type: Edit Record (campaigns table)
  • Filter: campaign_id == $input.campaign_id
  • Fields:
    • status: completed
    • completed_at: now()
Node 4: Return
  • Type: Return
  • Value: { "status": "completed", "campaign_id": "$input.campaign_id" }
Rate Limiting: Include a 1-2 second delay between /next calls to avoid overwhelming the API. SpiderIQ processes jobs asynchronously, so there’s no need to rush.

Step 5: Get and Store Results

After the campaign completes, fetch and store the aggregated results.

Function Stack: get_campaign_results

Input Parameters:
  • campaign_id (Text, required) - The SpiderIQ campaign ID
Node 1: Fetch Workflow Results
  • Type: External API Request
  • Method: GET
  • URL: https://spideriq.di-atomic.com/api/v1/jobs/spiderMaps/campaigns/$input.campaign_id/workflow-results
  • Headers:
    • Authorization: Bearer $env.SPIDERIQ_TOKEN
Node 2: Loop Through Locations
  • Type: Loop (For Each)
  • Array: $external.locations
  • Item Variable: location
Node 2.1: Loop Through Businesses
  • Type: Loop (For Each)
  • Array: $var.location.businesses
  • Item Variable: business
Node 2.1.1: Add Lead Record
  • Type: Add Record (leads table)
  • Fields:
    • campaign_id: $input.campaign_id
    • business_name: $var.business.business_name
    • business_address: $var.business.business_address
    • business_phone: $var.business.business_phone
    • business_rating: $var.business.business_rating
    • domain: $var.business.domain
    • location: $var.location.display_name
    • workflow_stage: $var.business.workflow_stage
    • created_at: now()
Node 2.1.2: Get Lead ID
  • Type: Create Variable
  • Name: lead_id
  • Value: $addrecord.id
Node 2.1.3: Loop Through Verified Emails
  • Type: Loop (For Each)
  • Array: $var.business.emails_verified
  • Item Variable: email
  • Condition: $var.email.status == "valid"
Node 2.1.3.1: Add Email Record
  • Type: Add Record (lead_emails table)
  • Fields:
    • lead_id: $var.lead_id
    • email: $var.email.email
    • status: $var.email.status
    • score: $var.email.score
    • is_deliverable: $var.email.is_deliverable
    • is_role_account: $var.email.is_role_account
End All LoopsNode 3: Return Summary
  • Type: Return
  • Value:
{
  "campaign_id": "$input.campaign_id",
  "total_businesses": "$external.total_businesses",
  "total_valid_emails": "$external.total_valid_emails"
}

Step 6: Schedule with Xano Tasks

Automate your lead generation with scheduled tasks.

Create a Scheduled Task

1

Navigate to Tasks

Go to your Xano workspace → Background Tasks
2

Create New Task

Click “Add Task” and configure:
  • Name: daily_lead_campaign
  • Schedule: Cron expression (e.g., 0 8 * * * for 8 AM daily)
3

Configure Task Logic

Build a Function Stack that:
  1. Creates a new campaign with today’s parameters
  2. Calls process_campaign to iterate locations
  3. Calls get_campaign_results to store leads
  4. Optionally sends notification (email, Slack webhook)

Complete Scheduled Task Function Stack

1. Create Campaign
   → Call: create_campaign(query: "restaurants", country_code: "US", min_population: 50000)
   → Store campaign_id

2. Process All Locations
   → Call: process_campaign(campaign_id: $step1.campaign_id)
   → Wait for completion

3. Fetch and Store Results
   → Call: get_campaign_results(campaign_id: $step1.campaign_id)

4. Send Notification (Optional)
   → External API Request to Slack/Email
   → Include: total_businesses, total_valid_emails

Step 7: Build a Dashboard API

Create endpoints for your frontend to display campaign progress.

Endpoint: GET /campaigns

Returns all campaigns with progress stats.
// Response
[
  {
    "campaign_id": "camp_fr_restaurants_20251223_abc123",
    "query": "restaurants",
    "country_code": "FR",
    "status": "completed",
    "total_locations": 42,
    "leads_count": 840,
    "valid_emails_count": 892,
    "created_at": "2025-12-23T10:30:00Z"
  }
]

Endpoint: GET /campaigns/{id}/leads

Returns leads for a specific campaign with filtering. Query Parameters:
  • min_rating - Filter by minimum Google rating
  • has_email - Only leads with valid emails
  • page, page_size - Pagination
// Response
{
  "leads": [
    {
      "business_name": "Le Petit Bistro",
      "business_address": "123 Rue de Rivoli, Paris",
      "business_rating": 4.5,
      "domain": "lepetitbistro.fr",
      "emails": [
        {"email": "contact@lepetitbistro.fr", "status": "valid", "score": 95}
      ]
    }
  ],
  "total": 840,
  "page": 1
}

Complete Xano Workflow

Here’s the complete automated flow:

Error Handling

Add error handling to your Function Stacks:
After each External API Request, add a Conditional:
Condition: $external.statusCode >= 400

If True:
  → Log Error: "SpiderIQ API Error: $external.statusCode"
  → Update campaign status to "error"
  → Stop execution / Return error
For transient failures, implement retry:
1. Create Variable: retry_count = 0
2. While retry_count < 3:
   → Try API call
   → If success: break
   → If fail: retry_count++, wait 5 seconds
3. If still failing: log and alert

Best Practices

Batch Processing

For large countries, split into regional campaigns to avoid timeouts.

Rate Limiting

Add 1-2 second delays between API calls. SpiderIQ queues jobs asynchronously.

Incremental Storage

Store leads as they come in via /next responses, not just at the end.

Monitoring

Log campaign progress and set up alerts for failures.

Next Steps