To integrate Oracle Eloqua with V0 by Vercel, generate a lead capture or marketing dashboard UI with V0, create a Next.js API route that calls Eloqua's REST API using Basic authentication with your site name and credentials, store them in Vercel environment variables, and deploy. Your app can submit contacts, track activities, and pull campaign performance data server-side.
Connect Oracle Eloqua Marketing Automation to V0-Built Lead Capture and Dashboard Pages
Oracle Eloqua powers enterprise B2B marketing at organizations running complex multi-touch campaigns with sophisticated lead scoring and CRM integration. While Eloqua's built-in landing pages and forms work, many marketing teams want custom-branded experiences that look nothing like a generic Eloqua form — a tailored lead capture page matching the brand perfectly, a custom campaign reporting dashboard with specific metrics, or a sales enablement tool pulling Eloqua data into a branded interface. V0 by Vercel is the fastest way to generate these custom interfaces.
Eloqua's REST API uses Basic authentication with a specific format: the site name (also called the company name or pod name) is prepended to the username as 'siteName\\username'. This combined credential is then Base64-encoded with the password in the standard Basic auth format. The Eloqua API base URL is service-specific and determined by calling the base URL endpoint first — Eloqua uses pod-based routing where different customers are on different pods (p01 through p09). Your first API call should be to https://login.eloqua.com/id to discover your pod's specific API URL.
Common integration patterns include: lead capture forms that create Eloqua contacts and subscribe them to nurture campaigns, marketing dashboards that pull email performance metrics and campaign activity, and CRM sync pages that display a contact's Eloqua history. All of these work well with V0-generated interfaces because V0 handles the form validation, table rendering, and chart components while your Next.js API routes handle the Eloqua business logic.
Integration method
Eloqua integrates with V0-generated Next.js apps through server-side API routes that authenticate with Eloqua's REST API using Basic authentication combining your Eloqua site name, username, and password. Contact creation, activity tracking, and campaign data retrieval all happen server-side through your API route, keeping credentials out of the browser. V0 generates the lead capture forms and marketing dashboard UI that connects to these routes.
Prerequisites
- An Oracle Eloqua account with API access enabled — Eloqua API access requires a licensed Eloqua user with Advanced Users - Marketing permission or an API user type
- Your Eloqua site name (also called company name) found at the top of your Eloqua login URL or in Eloqua Settings → Company Defaults
- An Eloqua username and password — create a dedicated API user in Eloqua for integration purposes rather than using a personal account
- Knowledge of your Eloqua pod URL — call https://login.eloqua.com/id with your credentials to discover the API base URL for your pod
- A V0 account at v0.dev and a Vercel account for deployment
Step-by-step guide
Generate the Lead Form or Marketing Dashboard UI with V0
Generate the Lead Form or Marketing Dashboard UI with V0
Open V0 at v0.dev and describe the marketing interface you want to build. For lead capture, describe the form fields matching the Eloqua contact fields you want to populate — common fields include first name, last name, email address, company, title, and phone number. For a reporting dashboard, describe the metrics and charts you want to display. V0 generates clean React form components with built-in validation using shadcn/ui and Tailwind CSS. When prompting V0, be specific about the form submission behavior: what endpoint it calls (POST /api/eloqua/contacts), what happens on success (show a thank you state), and how errors are displayed (inline error messages vs. toast notifications). For marketing dashboards, tell V0 the data shape — what columns to show in tables, what metrics to display in KPI cards, what chart types to use. V0's generated components handle form state, loading states, and error states natively with React hooks. Push the generated code to GitHub using V0's Git panel after you're satisfied with the layout.
Create a professional B2B lead generation form with a two-column layout on desktop (stacked on mobile). Left column: company overview with headline 'Download Our 2026 B2B Marketing Report', bullet points listing 3 key insights, and a preview of the report cover. Right column: form with fields for First Name, Last Name, Work Email (with validation), Company, and Job Title. Add a submit button 'Get Free Report' that shows a loading spinner on click and posts to POST /api/eloqua/contacts. On success, replace the form with a success state showing a checkmark, 'Report sent to your email!' and a share button. Use a professional navy and gold color palette.
Paste this in V0 chat
Pro tip: Ask V0 to include client-side email validation that checks for work email addresses (rejecting @gmail.com, @yahoo.com, etc.) since Eloqua lead capture pages are typically for B2B audiences and filtering personal emails improves data quality.
Expected result: A professional B2B lead capture form or marketing dashboard renders in V0's preview with proper form validation, loading states, and success/error handling connected to /api/eloqua/contacts.
Discover Your Eloqua API Base URL and Create the Contacts Route
Discover Your Eloqua API Base URL and Create the Contacts Route
Eloqua uses pod-based routing — your specific API base URL depends on which infrastructure pod your organization is hosted on. Before creating API routes, call the discovery endpoint to find your base URL. The discovery endpoint at https://login.eloqua.com/id returns the base URL for your pod when called with your credentials. Once you have the base URL (format: https://secure.p04.eloqua.com for pod 4, for example), all subsequent API calls use this URL. Eloqua's REST API uses Basic authentication with a combined credential string: your site name, a backslash, and your username, all Base64-encoded with your password. In code, this is Buffer.from('siteName\\username:password').toString('base64'). The contact creation endpoint is POST /api/REST/2.0/data/contact and accepts a JSON body with field names matching Eloqua's contact field names. Standard fields are firstName, lastName, emailAddress, company, title, and businessPhone. Custom fields use their field ID in the format C_FieldName. The contact create endpoint returns the created contact object with an ID that you can use for subsequent activity tracking calls.
1// app/api/eloqua/contacts/route.ts2import { NextRequest, NextResponse } from 'next/server';34const ELOQUA_SITE = process.env.ELOQUA_SITE_NAME;5const ELOQUA_USER = process.env.ELOQUA_USERNAME;6const ELOQUA_PASS = process.env.ELOQUA_PASSWORD;7const ELOQUA_BASE_URL = process.env.ELOQUA_BASE_URL; // e.g., https://secure.p04.eloqua.com89function getAuthHeader(): string {10 const combined = `${ELOQUA_SITE}\\${ELOQUA_USER}:${ELOQUA_PASS}`;11 return `Basic ${Buffer.from(combined).toString('base64')}`;12}1314interface ContactRequest {15 firstName: string;16 lastName: string;17 emailAddress: string;18 company?: string;19 title?: string;20 businessPhone?: string;21}2223export async function POST(request: NextRequest) {24 if (!ELOQUA_SITE || !ELOQUA_USER || !ELOQUA_PASS || !ELOQUA_BASE_URL) {25 return NextResponse.json(26 { error: 'Eloqua is not configured' },27 { status: 500 }28 );29 }3031 let body: ContactRequest;32 try {33 body = await request.json();34 } catch {35 return NextResponse.json({ error: 'Invalid request body' }, { status: 400 });36 }3738 if (!body.emailAddress || !body.firstName || !body.lastName) {39 return NextResponse.json(40 { error: 'emailAddress, firstName, and lastName are required' },41 { status: 400 }42 );43 }4445 try {46 const response = await fetch(`${ELOQUA_BASE_URL}/api/REST/2.0/data/contact`, {47 method: 'POST',48 headers: {49 Authorization: getAuthHeader(),50 'Content-Type': 'application/json',51 Accept: 'application/json',52 },53 body: JSON.stringify({54 firstName: body.firstName,55 lastName: body.lastName,56 emailAddress: body.emailAddress,57 company: body.company || '',58 title: body.title || '',59 businessPhone: body.businessPhone || '',60 }),61 });6263 if (!response.ok) {64 const errorText = await response.text();65 throw new Error(`Eloqua API error ${response.status}: ${errorText}`);66 }6768 const contact = await response.json();6970 return NextResponse.json({71 success: true,72 contactId: contact.id,73 });74 } catch (error) {75 const message = error instanceof Error ? error.message : 'Unknown error';76 console.error('Eloqua contact creation failed:', message);77 return NextResponse.json(78 { error: 'Failed to create contact', details: message },79 { status: 500 }80 );81 }82}Pro tip: Call https://login.eloqua.com/id with your credentials before hardcoding any base URL. The response includes 'urls.base' which is your correct API base URL. Hardcoding pod URLs is error-prone since Eloqua may migrate your organization between pods.
Expected result: POST /api/eloqua/contacts creates a new contact in Eloqua and returns { success: true, contactId: '...' }. The contact appears in Eloqua's contact database within seconds.
Add Campaign Data Retrieval for Reporting Dashboards
Add Campaign Data Retrieval for Reporting Dashboards
For marketing reporting use cases, create a GET route that fetches Eloqua campaign and email send data. Eloqua's REST API v2 provides endpoints for email campaigns at /api/REST/2.0/assets/emails and campaign data at /api/REST/2.0/assets/campaigns. Email send activity and performance metrics (opens, clicks, bounces) are accessed through the Bulk API at /api/bulk/2.0/campaigns — note that Eloqua has two API endpoints: the standard REST API for CRUD operations and the Bulk API for reporting and large data exports. For simple dashboard metrics, the REST API's activity endpoints at /api/REST/2.0/data/activities/contact/{contactId} work well for individual contact activity. For aggregate campaign metrics, use the Bulk API which requires a different flow: create an export definition specifying the fields you want, then sync the export to retrieve the data. This two-step process is more complex but handles large datasets without timeout issues. For most V0-built dashboards that need basic campaign metrics, querying the email assets endpoint and pulling send counts provides a good starting point without needing the full Bulk API flow.
Add a Campaign Analytics section to the dashboard. Show a filterable table of email campaigns with Name, Send Date, Subject Line, and three metric columns. Each metric column should show the number with a trend arrow (up/down compared to previous send). Add a toggle to switch between Campaigns and Contacts view. In Contacts view, show a search field for looking up contact activity history. Use GET /api/eloqua/campaigns for the campaign list and GET /api/eloqua/contacts?email={query} for contact lookup.
Paste this in V0 chat
1// app/api/eloqua/campaigns/route.ts2import { NextRequest, NextResponse } from 'next/server';34const ELOQUA_BASE_URL = process.env.ELOQUA_BASE_URL;56function getAuthHeader(): string {7 const combined = `${process.env.ELOQUA_SITE_NAME}\\${process.env.ELOQUA_USERNAME}:${process.env.ELOQUA_PASSWORD}`;8 return `Basic ${Buffer.from(combined).toString('base64')}`;9}1011export async function GET(request: NextRequest) {12 if (!ELOQUA_BASE_URL) {13 return NextResponse.json({ error: 'Eloqua not configured' }, { status: 500 });14 }1516 const { searchParams } = new URL(request.url);17 const page = searchParams.get('page') || '1';18 const count = searchParams.get('count') || '25';1920 try {21 const response = await fetch(22 `${ELOQUA_BASE_URL}/api/REST/2.0/assets/campaigns?page=${page}&count=${count}&depth=complete`,23 {24 headers: {25 Authorization: getAuthHeader(),26 Accept: 'application/json',27 },28 }29 );3031 if (!response.ok) {32 throw new Error(`Eloqua campaigns error: ${response.status}`);33 }3435 const data = await response.json();3637 return NextResponse.json({38 campaigns: data.elements || [],39 total: data.total || 0,40 page: data.page,41 });42 } catch (error) {43 const message = error instanceof Error ? error.message : 'Unknown error';44 return NextResponse.json({ error: message }, { status: 500 });45 }46}Pro tip: Eloqua's API has two separate systems: the REST API (for CRUD on contacts, campaigns, emails) and the Bulk API (for large data exports and reporting). For real-time dashboards with up to a few hundred records, the REST API works fine. For reporting on millions of email sends, use the Bulk API's async export pattern.
Expected result: GET /api/eloqua/campaigns returns a paginated list of Eloqua campaigns with their details and status information.
Set Environment Variables in Vercel and Deploy
Set Environment Variables in Vercel and Deploy
Push your project to GitHub and configure Eloqua credentials in the Vercel Dashboard. Navigate to your project → Settings → Environment Variables. Add four variables: ELOQUA_SITE_NAME with your Eloqua company/site name (this is the prefix shown before the backslash in your Eloqua login), ELOQUA_USERNAME with the dedicated API user's Eloqua username, ELOQUA_PASSWORD with the API user's password, and ELOQUA_BASE_URL with your pod's base URL (e.g., https://secure.p04.eloqua.com). None of these should have the NEXT_PUBLIC_ prefix as they are server-only credentials. Create a dedicated Eloqua API user specifically for this integration rather than using a named marketer's account — this ensures the integration doesn't break when employees leave, and you can control exactly which permissions the API user has. In Eloqua, go to Settings → User Management → Users and create a new API User type. Grant it the minimum permissions needed: contact read/write for lead capture, campaign read for reporting. After saving the environment variables, trigger a redeployment in Vercel. Test the live deployment by submitting the lead capture form and verifying the contact appears in Eloqua's contact database.
Pro tip: Create a dedicated Eloqua API user with a non-expiring password and restricted permissions rather than using a personal marketing account. Eloqua admin accounts have access to all data — a dedicated API user with minimal permissions reduces security risk.
Expected result: Vercel deployment succeeds, form submissions from the live URL create contacts in Eloqua in real time, and the marketing dashboard displays live campaign data from your Eloqua account.
Common use cases
B2B Lead Capture with Eloqua Contact Creation
A gated content download page where visitors enter their details to receive a whitepaper or demo request. On submission, the form creates or updates a contact in Eloqua, adds them to a nurture campaign, and logs the form submission activity for lead scoring.
Create a gated content download form for a B2B SaaS company. Fields: First Name, Last Name, Work Email, Company Name, Job Title, and Company Size dropdown (1-50, 51-200, 201-1000, 1000+). Include a 'I agree to receive marketing emails' checkbox (required). A Download Now button submits to POST /api/eloqua/contacts. On success, show a download confirmation card with a document icon, thank you message, and a Proceed to Download button. Use a professional dark navy and white color scheme with the company logo placeholder at top.
Copy this prompt to try it in V0
Email Campaign Performance Dashboard
An internal marketing dashboard showing Eloqua email campaign sends, open rates, click rates, and bounce rates in a clean table with sparkline trend charts. Marketing managers can filter by date range and campaign without logging into Eloqua's complex interface.
Build a marketing performance dashboard with a header showing summary KPI cards for Total Sends, Average Open Rate, Average Click Rate, and Unsubscribes This Month. Below, show a filterable data table of email campaigns with columns for campaign name, send date, total recipients, open rate (with a mini bar chart), click rate, and unsubscribes. Include a date range picker for filtering and a search bar. Add a line chart at the top showing open rate trends over the last 30 days. Data from GET /api/eloqua/campaigns. Use a clean SaaS analytics style with indigo accents.
Copy this prompt to try it in V0
Contact Activity Lookup Tool
A sales team tool where reps can look up a contact's Eloqua activity history by email address — seeing what emails they opened, what pages they visited, what forms they submitted, and their current lead score. This surfaces valuable context before a sales call.
Design a contact lookup tool with a prominent search bar at the top for entering an email address. Clicking Search fetches from GET /api/eloqua/contacts?email={email} and displays a contact profile card with name, company, title, lead score badge, and last activity date. Below the card, show an activity timeline with entries for Email Opens (envelope icon), Form Submissions (clipboard icon), and Website Visits (globe icon), each with the activity name and timestamp. Show an empty state if no contact is found. Use a clean CRM-style layout with a white background and gray card borders.
Copy this prompt to try it in V0
Troubleshooting
API returns 401 Unauthorized despite using correct username and password
Cause: The Basic auth credential format is wrong. Eloqua requires the site name to be prepended to the username with a backslash separator, not just the username and password.
Solution: Verify the auth header format is 'SiteName\\Username:Password' before Base64 encoding. The double backslash in JavaScript source code produces a single backslash in the actual string. You can test the correct format by calling the Eloqua REST API from Postman with the Basic Auth type and entering 'SiteName\Username' (with single backslash) as the username field.
1// Correct format: siteName\username:password2const combined = `${siteName}\\${username}:${password}`; // \\ = one backslash in the string3const encoded = Buffer.from(combined).toString('base64');4const header = `Basic ${encoded}`;Contact creation returns 400 Bad Request with validation errors
Cause: Required Eloqua contact fields are missing or the email address format fails Eloqua's validation. Eloqua validates email format strictly and rejects malformed addresses.
Solution: Ensure emailAddress, firstName, and lastName are all present and non-empty. Validate the email format on the client side before sending. Check the error response body — Eloqua returns detailed validation messages explaining which fields failed and why.
API calls work locally but fail in Vercel production with 'fetch failed' error
Cause: The ELOQUA_BASE_URL environment variable is not set in Vercel, or the pod URL is incorrect for the production environment.
Solution: Go to Vercel Dashboard → Settings → Environment Variables and verify ELOQUA_BASE_URL is set correctly. Discover the correct URL by calling https://login.eloqua.com/id — the response contains your pod's base URL in the urls.base field. Confirm the variable is set for the Production environment scope, not just Preview or Development.
Campaign list endpoint returns empty array despite active campaigns in Eloqua
Cause: The API user account does not have permission to read campaign assets, or the campaigns are in a draft state not returned by the default filter.
Solution: Add the campaigns:read permission to the Eloqua API user's profile in Eloqua Settings → User Management. Also try adding ?status=Active to the campaigns endpoint to explicitly filter for active campaigns, or remove filters to see all campaigns regardless of status.
Best practices
- Use a dedicated Eloqua API user with minimal required permissions rather than personal marketing user credentials — this prevents integration breakage when employees leave
- Discover your Eloqua API base URL dynamically by calling https://login.eloqua.com/id rather than hardcoding a pod URL, since Eloqua may migrate your organization
- Validate email addresses on the client side before sending to Eloqua — the API will reject malformed emails with a 400 error and returning a clear validation message is better UX than an API error
- Store the Eloqua site name, username, and password as separate Vercel environment variables rather than a combined encoded string — this makes rotation easier
- Create separate Eloqua contact field mappings in your API route rather than accepting arbitrary field names from the frontend — this prevents clients from writing to unexpected Eloqua fields
- Log Eloqua API errors with the full response body, not just the status code — Eloqua returns detailed validation messages that are essential for debugging contact creation failures
- For high-volume lead capture (thousands of submissions per hour), use Eloqua's Bulk API for contact imports rather than individual REST API calls to avoid rate limiting
Alternatives
Use Marketo instead of Eloqua if your organization uses Adobe Experience Cloud — Marketo's REST API uses OAuth2 with simpler credential management and has more extensive developer documentation.
Choose Pardot (Marketing Cloud Account Engagement) instead if your CRM is Salesforce — Pardot integrates natively with Salesforce and uses the same OAuth2 flow as other Salesforce APIs.
Consider HubSpot Marketing Hub if you want a simpler API with better documentation — HubSpot uses straightforward API key or OAuth2 authentication without the site name prefix complexity of Eloqua.
Frequently asked questions
What is the difference between Eloqua's REST API and Bulk API?
Eloqua has two separate APIs: the REST API (at /api/REST/2.0/) handles real-time CRUD operations for contacts, campaigns, and email assets — ideal for form submissions and individual contact lookups. The Bulk API (at /api/bulk/2.0/) handles large-scale data exports and imports asynchronously — necessary for reporting dashboards that need millions of email activity records. Use REST for real-time operations and Bulk for batch reporting.
How do I find my Eloqua site name (company name)?
Your Eloqua site name appears in your login URL as a subdomain or prefix. Go to https://login.eloqua.com/id and pass your Basic auth credentials (siteName\username:password) — the response JSON contains your site name, base URL, and username. Alternatively, in Eloqua navigate to Settings → Company Defaults where the company name (site name) is displayed at the top.
Does Eloqua offer a sandbox environment for testing integrations?
Eloqua provides a 'test environment' that must be specifically provisioned by Oracle — it's not automatically available with standard licenses. Contact your Oracle account manager to request a test environment. For development purposes, many teams create a dedicated test list or segment in their production Eloqua instance and limit API testing to that segment to avoid affecting production marketing data.
How do I add a contact to an Eloqua email campaign list from my V0 app?
Eloqua uses contact lists (static) and segments (dynamic query-based) for campaign targeting. To add a contact to a static list, first create the contact via POST /api/REST/2.0/data/contact, then call POST /api/REST/2.0/data/contact/list/{listId}/contacts to add them to the list using their contact ID. You can find list IDs in Eloqua under Contacts → Lists or via GET /api/REST/2.0/assets/contact/lists.
Can I use Eloqua with Vercel's serverless functions or will the connection time out?
Eloqua REST API calls typically respond in under 2 seconds for individual contact operations, well within Vercel's serverless function timeouts. Bulk API exports are asynchronous and require polling, so you'd check export status in a separate API call rather than waiting in a single function. For dashboards loading campaign data, implement request timeouts of 10 seconds and show partial data if some requests fail.
What Eloqua user permissions does the API integration need?
For lead capture (creating contacts), the API user needs the 'Contacts - Create/Edit' permission. For reading campaigns and email assets, add 'Campaigns - View' and 'Email - View'. For activity tracking and reporting, add 'Activities - View'. You can create an API-specific user role in Eloqua Settings → User Management → Roles with only these permissions, minimizing the security footprint of your integration.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation