All posts
Guide

From API to Internal Dashboards: A Customer Story

See how an agency built a white-label AEO dashboard using SearchFit's API to track AI visibility at scale for multiple clients.

KKevin16 minutes read

From API to internal dashboards: A Customer Story

Six months ago, a mid-sized digital marketing agency managing 40+ B2B SaaS clients faced a crisis nobody was talking about yet. Their clients' organic traffic was steady. Their Google rankings looked solid. But when the agency's strategists searched for their clients' solutions in ChatGPT, Perplexity, and Gemini, they found almost nothing.

No citations. No brand mentions. No recommendations to use their clients' products. Meanwhile, competitors were showing up in every AI query result.

The agency knew this was a real problem, not theoretical. AI search was already driving qualified traffic for some of their competitors' clients. But they had no way to track it, measure it, or prove it to their own clients. They were flying blind.

They needed a solution that could:

  • Monitor brand visibility across multiple AI platforms in real time
  • Track which competitor brands were getting cited instead
  • Show clients exactly where they were losing visibility
  • Prove ROI when they optimized content for AI search

They needed more than a tool. They needed a platform they could white-label and integrate into their own client dashboard, something that would look and feel like their own product, not a third-party bolt-on.

This is the story of how they built it.

Understanding the Opportunity: Why White-Label Matters

The agency's leadership team understood something critical: their clients didn't want another SaaS login. They didn't want to juggle five different platforms. They wanted one dashboard, the agency's dashboard, that showed them everything they needed to know about their visibility, including AI search performance.

Building that from scratch would take months and cost six figures. They'd need engineers, infrastructure, data pipelines, and ongoing maintenance. They'd need to handle API rate limits, data storage, and real-time updates across six different AI platforms.

Or they could use an API.

The agency discovered SearchFit's API and realized it was the missing piece. SearchFit already tracked brand visibility across ChatGPT, Perplexity, Gemini, Claude, Grok, and Google. The platform had the data pipeline, the AI platform integrations, and the tracking infrastructure already built. All the agency needed to do was pull that data into their own dashboard using the API.

This approach had a clear business advantage: they could launch white-label AI visibility tracking in weeks instead of months. They could offer it to clients as a native feature of their platform. And they could own the client relationship while leveraging SearchFit's technical infrastructure.

White-labeling isn't just about branding. It's about control, speed, and margins. When you own the dashboard, you own the client experience. You control the pricing. You control the narrative around what the data means.

As Embeddable's customer stories demonstrate, companies building insights and dashboards with embedded platforms often see faster time-to-market and lower engineering overhead. The same principle applies here: use the API as your foundation, build the experience on top.

Prerequisites: What You Need Before You Start

Before diving into API integration, make sure you have these pieces in place:

1. API Access and Credentials

You'll need a SearchFit account with API access enabled. This means signing up for a plan that includes API credentials, typically a tier above basic analytics. You'll receive an API key and endpoint documentation. Keep these credentials secure; treat them like database passwords.

2. A Dashboard Platform or Development Team

You need somewhere to display the data. This could be:

  • An existing dashboard platform you already use (like a BI tool, Tableau, Looker, or similar)
  • A custom-built dashboard your engineering team maintains
  • A no-code dashboard builder like Embeddable or similar platforms that can consume REST APIs
  • Your existing client portal with new widgets added

The agency in this story had a basic client portal built on React. They had two engineers on staff who could handle API integration and frontend work.

3. Engineering Capacity

You don't need a large team, but you do need someone who understands:

  • REST API consumption (GET requests, JSON parsing, error handling)
  • Data storage and caching (so you're not hitting the API on every page load)
  • Frontend development (displaying data in charts, tables, and visualizations)
  • Basic security (API key management, rate limiting on your own endpoints)

If you don't have in-house engineering capacity, you have options: hire a freelance developer, use a no-code integration platform like Zapier or Make, or partner with an agency that specializes in API integrations.

4. Client Onboarding Process

Decide how you'll add new brands to track. Will clients submit their brand names through a form? Will you set them up manually? Will there be approval workflows? The agency in this story built a simple form where account managers could add new brands, and the API would automatically start tracking them.

5. Data Storage Plan

SearchFit's API gives you real-time data, but you'll want to store historical data so you can show trends over time. Decide whether you'll use a relational database (PostgreSQL, MySQL) or a data warehouse (Snowflake, BigQuery). The agency used PostgreSQL to keep costs low.

Step 1: Set Up Your Development Environment and Secure API Credentials

Start by creating a secure environment for your API credentials. Never hardcode API keys in your codebase or commit them to version control.

Create an environment file:

If you're using Node.js or Python, create a .env file in your project root:

SEARCHFIT_API_KEY=your_actual_api_key_here
SEARCHFIT_API_BASE_URL=https://api.searchfit.ai
DATABASE_URL=your_database_connection_string

Add .env to your .gitignore so it never gets committed to version control.

Load credentials at runtime:

In your application code, load these variables from environment variables, not from files:

const apiKey = process.env.SEARCHFIT_API_KEY;
const baseUrl = process.env.SEARCHFIT_API_BASE_URL;

Or in Python:

import os
api_key = os.getenv('SEARCHFIT_API_KEY')
base_url = os.getenv('SEARCHFIT_API_BASE_URL')

Set up your development database:

Create a local development database where you'll store tracked brands and historical visibility data. You'll query this database to populate your dashboard, not the API directly (more on this in Step 3).

The agency used PostgreSQL and created a simple schema:

CREATE TABLE tracked_brands (
id SERIAL PRIMARY KEY,
client_id INTEGER NOT NULL,
brand_name VARCHAR(255) NOT NULL,
searchfit_brand_id VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE visibility_snapshots (
id SERIAL PRIMARY KEY,
brand_id INTEGER NOT NULL REFERENCES tracked_brands(id),
platform VARCHAR(50),
citation_count INTEGER,
ranking_position INTEGER,
visibility_score DECIMAL,
captured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

This schema lets you track multiple brands per client and store daily snapshots of their visibility across platforms.

Step 2: Make Your First API Call and Understand the Response Structure

Once your environment is set up, make a test API call to SearchFit. You'll need to know:

  • The endpoint for brand tracking data
  • Required query parameters (brand name, date range, platforms)
  • The response structure (what fields you'll receive)

Here's a sample API call in JavaScript using the fetch API:

const fetchBrandVisibility = async (brandName) => {
const apiKey = process.env.SEARCHFIT_API_KEY;
const baseUrl = process.env.SEARCHFIT_API_BASE_URL;

const response = await fetch(
`${baseUrl}/api/v1/brands/visibility?name=${encodeURIComponent(brandName)}`,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
}
);

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

const data = await response.json();
return data;
};

A typical response from SearchFit's API might look like this:

{
"brand": "Acme SaaS",
"visibility": {
"chatgpt": {
"citation_count": 12,
"ranking_position": 3,
"visibility_score": 0.78,
"last_updated": "2024-01-15T10:30:00Z"
},
"perplexity": {
"citation_count": 8,
"ranking_position": 5,
"visibility_score": 0.65,
"last_updated": "2024-01-15T10:30:00Z"
},
"gemini": {
"citation_count": 15,
"ranking_position": 2,
"visibility_score": 0.82,
"last_updated": "2024-01-15T10:30:00Z"
}
}
}

Understand this structure because you'll map these fields into your database schema. The agency stored the visibility score and citation count for each platform, then calculated trends over time.

Handle API errors gracefully:

The API might return rate limit errors (429), authentication errors (401), or brand-not-found errors (404). Build error handling into your integration:

const fetchBrandVisibility = async (brandName) => {
try {
const response = await fetch(apiUrl, options);

if (response.status === 429) {
// Rate limited. Wait and retry.
console.log('Rate limited. Backing off...');
await new Promise(resolve => setTimeout(resolve, 60000));
return fetchBrandVisibility(brandName);
}

if (response.status === 401) {
throw new Error('Invalid API key');
}

if (response.status === 404) {
console.log(`Brand not found: ${brandName}`);
return null;
}

return await response.json();
} catch (error) {
console.error('API call failed:', error);
throw error;
}
};

Step 3: Build a Data Pipeline to Store Visibility Data

Don't call the API every time a user loads your dashboard. That's slow and expensive. Instead, build a background job that fetches data from SearchFit on a schedule and stores it in your database.

The agency set up a cron job that ran every 6 hours:

// This runs every 6 hours via a cron service
const syncVisibilityData = async () => {
// 1. Get all tracked brands from your database
const brands = await db.query('SELECT * FROM tracked_brands');

// 2. For each brand, fetch current visibility from SearchFit API
for (const brand of brands) {
try {
const visibility = await fetchBrandVisibility(brand.brand_name);

// 3. Store the snapshot in your database
await db.query(
`INSERT INTO visibility_snapshots 
(brand_id, platform, citation_count, ranking_position, visibility_score, captured_at)
VALUES ($1, $2, $3, $4, $5, NOW())`,
[
brand.id,
'chatgpt',
visibility.chatgpt.citation_count,
visibility.chatgpt.ranking_position,
visibility.chatgpt.visibility_score
]
);

// Repeat for other platforms (perplexity, gemini, claude, etc.)
} catch (error) {
console.error(`Failed to sync ${brand.brand_name}:`, error);
// Continue with next brand instead of failing
}
}
};

This approach gives you several advantages:

  • Speed: Dashboard loads are instant because data is already in your database
  • Cost: You make fewer API calls overall
  • Reliability: If SearchFit's API is temporarily down, your dashboard still works with cached data
  • Trending: You can calculate week-over-week and month-over-month changes

Pro Tip: Store raw API responses in a separate table too. This gives you the flexibility to re-parse or re-analyze data later without re-fetching from the API.

Step 4: Design Your Internal Dashboard Schema and Frontend Components

Now that you're storing visibility data, you need to display it. The agency's white-label dashboard had three main views:

View 1: Executive Summary

Shows a high-level overview of AI visibility across all platforms:

SELECT 
platform,
AVG(visibility_score) as avg_visibility,
SUM(citation_count) as total_citations,
MAX(ranking_position) as best_position
FROM visibility_snapshots
WHERE brand_id IN (SELECT id FROM tracked_brands WHERE client_id = $1)
AND captured_at > NOW() - INTERVAL '30 days'
GROUP BY platform
ORDER BY avg_visibility DESC;

This query powers a card-based layout showing each platform's performance.

View 2: Trend Analysis

Shows how visibility has changed over time:

SELECT 
DATE(captured_at) as date,
platform,
AVG(visibility_score) as avg_visibility,
SUM(citation_count) as total_citations
FROM visibility_snapshots
WHERE brand_id = $1
AND captured_at > NOW() - INTERVAL '90 days'
GROUP BY DATE(captured_at), platform
ORDER BY date DESC;

Display this as line charts showing visibility trends for each platform.

View 3: Competitive Intelligence

Compare your brand's visibility against competitors:

SELECT 
b.brand_name,
platform,
AVG(visibility_score) as avg_visibility,
SUM(citation_count) as total_citations
FROM visibility_snapshots vs
JOIN tracked_brands b ON vs.brand_id = b.id
WHERE b.client_id = $1
AND vs.captured_at > NOW() - INTERVAL '30 days'
GROUP BY b.brand_name, platform
ORDER BY platform, avg_visibility DESC;

This shows how your brand stacks up against competitors you're tracking.

The agency built these views using React components that consumed GraphQL endpoints (which themselves queried the PostgreSQL database). By separating the data layer from the presentation layer, they made it easy to add new visualizations later.

Step 5: Implement Real-Time Alerts and Notifications

Visibility data only matters if you act on it. The agency added automated alerts that notify account managers when:

  • A client's visibility drops more than 20% week-over-week
  • A competitor suddenly appears in top 3 results
  • Citation count drops below a threshold

Here's how they implemented it:

const checkVisibilityAlerts = async () => {
// Get latest visibility for each brand
const latestSnapshots = await db.query(`
SELECT DISTINCT ON (brand_id, platform) 
brand_id, platform, visibility_score, captured_at
FROM visibility_snapshots
ORDER BY brand_id, platform, captured_at DESC
`);

// Get previous week's average
const previousWeek = await db.query(`
SELECT brand_id, platform, AVG(visibility_score) as avg_score
FROM visibility_snapshots
WHERE captured_at > NOW() - INTERVAL '14 days'
AND captured_at < NOW() - INTERVAL '7 days'
GROUP BY brand_id, platform
`);

// Compare and create alerts
for (const latest of latestSnapshots) {
const previous = previousWeek.find(
p => p.brand_id === latest.brand_id && p.platform === latest.platform
);

if (previous) {
const percentChange = ((latest.visibility_score - previous.avg_score) / previous.avg_score) * 100;

if (percentChange < -20) {
// Create alert
await db.query(
`INSERT INTO alerts (brand_id, platform, alert_type, severity, message)
VALUES ($1, $2, 'visibility_drop', 'high', $3)`,
[latest.brand_id, latest.platform, 
`Visibility dropped ${Math.abs(percentChange).toFixed(1)}% on ${latest.platform}`]
);

// Notify account manager
const brand = await db.query('SELECT * FROM tracked_brands WHERE id = $1', [latest.brand_id]);
await sendSlackNotification(brand.client_id, `⚠️ Visibility alert for ${brand.brand_name}`);
}
}
}
};

The agency integrated these alerts with Slack, so account managers got notified immediately when something changed. This turned data into actionable intelligence.

Step 6: White-Label the Dashboard and Customize Branding

This is where the white-label advantage really shows. The agency's dashboard needed to feel like their own product, not a SearchFit integration.

They implemented dynamic branding:

// In their dashboard config
const dashboardConfig = {
branding: {
logo: '/logos/agency-logo.png',
primaryColor: '#0066CC',
secondaryColor: '#F0F4F8',
fontFamily: 'Inter, sans-serif'
},
features: {
showSearchfitBranding: false,  // Hide third-party branding
showPoweredByLine: false,
customMetadata: true
},
pages: {
dashboard: '/client/dashboard',
settings: '/client/settings',
reports: '/client/reports'
}
};

Clients logged into the agency's portal and saw a unified dashboard that tracked everything, Google rankings, traffic, and now AI visibility, all in one place. They had no idea SearchFit's API was powering the AI search data.

This is a significant competitive advantage. Clients perceived the agency as a full-stack visibility partner, not as someone cobbling together third-party tools.

Pro Tip: As Traceable's customer stories show, companies that white-label APIs effectively often see higher customer retention because the product feels like a native part of the platform.

Step 7: Build Reporting and Export Functionality

Dashboards are great for daily monitoring, but clients also need reports they can share with their leadership teams.

The agency built automated monthly reports that:

  • Summarized AI visibility trends
  • Compared performance across platforms
  • Highlighted wins and opportunities
  • Included competitor benchmarking
  • Recommended content optimizations
const generateMonthlyReport = async (brandId, month) => {
const startDate = new Date(month.year, month.month - 1, 1);
const endDate = new Date(month.year, month.month, 0);

// Get visibility data for the month
const monthlyData = await db.query(`
SELECT platform, AVG(visibility_score) as avg_visibility, 
SUM(citation_count) as total_citations
FROM visibility_snapshots
WHERE brand_id = $1
AND captured_at >= $2
AND captured_at <= $3
GROUP BY platform
`, [brandId, startDate, endDate]);

// Get previous month for comparison
const prevStartDate = new Date(month.year, month.month - 2, 1);
const prevEndDate = new Date(month.year, month.month - 1, 0);

const previousData = await db.query(`
SELECT platform, AVG(visibility_score) as avg_visibility
FROM visibility_snapshots
WHERE brand_id = $1
AND captured_at >= $2
AND captured_at <= $3
GROUP BY platform
`, [brandId, prevStartDate, prevEndDate]);

// Calculate trends
const trends = monthlyData.map(current => {
const previous = previousData.find(p => p.platform === current.platform);
return {
platform: current.platform,
visibility: current.avg_visibility,
citations: current.total_citations,
trend: previous ? 
((current.avg_visibility - previous.avg_visibility) / previous.avg_visibility * 100).toFixed(1) : 
'N/A'
};
});

// Generate PDF report
const report = await generatePDF({
title: `AI Visibility Report - ${month}`,
sections: [
{ type: 'summary', data: trends },
{ type: 'chart', data: monthlyData },
{ type: 'recommendations', data: await getRecommendations(brandId) }
]
});

return report;
};

The agency set these reports to email automatically on the first of each month. Clients loved having a professional, branded report they could share with their teams.

Step 8: Optimize API Usage and Manage Costs

As the agency scaled from 5 clients to 40+, API costs became a real concern. They optimized by:

1. Batching Requests

Instead of calling the API once per brand, they batched multiple brands into single requests where possible:

const fetchMultipleBrands = async (brandNames) => {
const response = await fetch(`${baseUrl}/api/v1/brands/visibility/batch`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ brands: brandNames })
});
return response.json();
};

2. Reducing Sync Frequency

They started syncing every 6 hours but found that daily syncs were sufficient for most clients. They offered premium clients more frequent updates (every 4 hours) at a higher price point.

3. Caching and TTL

They added Redis caching with a 4-hour TTL for frequently accessed data:

const getBrandVisibility = async (brandId) => {
const cacheKey = `visibility:${brandId}`;

// Check cache first
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);

// If not cached, fetch from database
const data = await db.query(
'SELECT * FROM visibility_snapshots WHERE brand_id = $1 ORDER BY captured_at DESC LIMIT 1',
[brandId]
);

// Cache for 4 hours
await redis.setex(cacheKey, 14400, JSON.stringify(data));

return data;
};

4. Selective Data Storage

They didn't store every data point from the API. They stored aggregated metrics (average visibility, total citations) rather than raw response data, reducing database storage by 60%.

These optimizations cut their API costs by 40% while maintaining the same level of insight for clients.

Step 9: Implement Security and Access Controls

With 40+ clients' data in the system, security became critical. The agency implemented:

Role-Based Access Control (RBAC)

const canAccessBrand = (userId, brandId) => {
// Check if user's client owns this brand
return db.query(`
SELECT 1 FROM tracked_brands
WHERE id = $1
AND client_id = (
SELECT client_id FROM users WHERE id = $2
)
`, [brandId, userId]);
};

// Middleware to check access
app.get('/api/brands/:brandId/visibility', async (req, res) => {
const hasAccess = await canAccessBrand(req.user.id, req.params.brandId);
if (!hasAccess) return res.status(403).json({ error: 'Forbidden' });

// Return data
});

API Key Rotation

They rotated SearchFit API keys every 90 days and stored old keys in a separate vault in case they needed to audit historical API calls.

Audit Logging

Every API call to SearchFit was logged with timestamp, requesting user, and data accessed:

const logAPICall = async (userId, brandId, action) => {
await db.query(`
INSERT INTO audit_logs (user_id, brand_id, action, timestamp)
VALUES ($1, $2, $3, NOW())
`, [userId, brandId, action]);
};

These practices ensured that each client only saw their own data and that the agency could audit who accessed what and when.

Step 10: Monitor Performance and Iterate

After launching, the agency monitored:

API Performance

  • Average response time: 200-400ms
  • Success rate: 99.2% (occasional rate limits or temporary outages)
  • Error rate: <0.5%

Dashboard Performance

  • Page load time: <2 seconds
  • Query performance: <500ms for most queries
  • Concurrent users: Tested up to 200 simultaneous users without degradation

Business Metrics

  • Client adoption: 85% of clients logged into the dashboard at least weekly
  • Feature usage: AI visibility section was accessed more frequently than initially expected
  • Retention: Clients who actively used the AI visibility dashboard had 40% higher retention rates

They used AWS CloudWatch for monitoring infrastructure and built custom dashboards in Grafana to track application health.

When they identified slow queries, they added indexes. When they saw API rate limit errors, they implemented exponential backoff. When clients requested new metrics, they added them to the data pipeline.

Results: What the Agency Achieved

Six months after launch, the agency had:

  • White-labeled AI visibility tracking for 40+ clients in a single platform
  • Reduced engineering overhead by using SearchFit's API instead of building their own tracking infrastructure
  • Increased customer stickiness by offering a feature competitors couldn't easily replicate
  • Created a new revenue stream by charging clients for AI visibility monitoring as a premium add-on
  • Improved client outcomes by identifying visibility gaps and recommending content optimizations
  • Shortened sales cycles by demonstrating AI visibility problems in real-time during sales conversations

One client saw their ChatGPT citations increase from 2 to 14 in three months after the agency identified and optimized their content for AI search. Another client discovered they were completely invisible in Perplexity and built a content strategy to address it.

The white-label dashboard became a competitive advantage. When prospects asked "How do you track AI visibility?", the agency could show a fully integrated dashboard that looked like their own product. Prospects couldn't tell it was powered by an API. It just looked like another feature of the agency's platform.

Key Takeaways: Building Your Own White-Label Dashboard

If you're considering building a white-label dashboard on top of an API, here are the lessons from this agency's experience:

1. Choose the Right Foundation

Don't build tracking infrastructure from scratch if a good API already exists. SearchFit's API saved this agency months of development time. Evaluate whether the API covers your use cases, has reliable uptime, and offers the data granularity you need.

2. Build a Data Pipeline, Not Just an API Wrapper

Calling an API on every dashboard load is slow and expensive. Store the data in your own database. Sync on a schedule. Cache aggressively. This gives you speed, cost efficiency, and resilience.

3. White-Labeling Requires More Than Cosmetics

It's not just about changing colors and logos. It's about integrating the data seamlessly into your existing platform, implementing access controls, and building reporting that feels native. Clients should never feel like they're using a third-party tool.

4. Start with Monitoring, Then Add Intelligence

First, track the metrics. Then, add alerts. Then, add recommendations. This phased approach lets you launch faster and iterate based on real usage patterns.

5. Security and Access Control Are Non-Negotiable

With multiple clients' data in one system, implement RBAC, audit logging, and API key rotation from day one. This isn't something you add later.

6. Optimize for Cost as You Scale

What works for 5 clients might be expensive for 50. Batch requests, reduce sync frequency, implement caching, and store aggregated data instead of raw responses. Monitor your API usage and adjust your strategy as you scale.

7. The Real Value Is in the Narrative

The data matters, but the story matters more. Reports, alerts, and recommendations that turn raw data into actionable insights are what drive client outcomes and retention.

This agency didn't just integrate an API. They built a complete white-label solution that became a core part of their value proposition. They used SearchFit's analytics capabilities as the foundation and built a client experience on top that felt like their own product.

If you're an agency managing multiple clients, or a SaaS company that needs to offer AI visibility tracking, this is the playbook: find a reliable API, build a data pipeline, white-label the experience, and iterate based on real client usage.

The agencies and companies that move fastest on AI visibility will own their client relationships and drive better outcomes. The ones that wait will find their clients using third-party tools and losing stickiness.

The time to build is now. The tools exist. The question is whether you'll use them to own your client experience or let someone else do it.

Get SearchFIT Weekly

What we are learning about getting brands cited in AI search, in your inbox every week. Unsubscribe any time.