Go to: Settings Tab β API Configuration Section
The Settings page has dedicated input fields for each API key:
- Meta (Facebook/Instagram) API Key
- Google Maps API Key
- Google My Business API Key
- TikTok Business API Key
- Backend Scraper Service URL
src/
βββ App.tsx # Main application component
βββ SettingsPage.tsx # β API keys are configured HERE
βββ apiServices.ts # β API calls are made HERE
βββ WebsiteScraperView.tsx # Website scraper UI
βββ types.ts # TypeScript type definitions
βββ mockData.ts # Demo data (used when no API keys)
This is where you enter and save your API keys. The keys are stored in browser localStorage.
What it does:
- Provides input fields for all API keys
- Tests API key validity
- Saves configuration to localStorage
- Shows connection status
How to use:
- Click on "Settings" in the sidebar
- Enter your API keys in the respective fields
- Click "Test Key" to verify each key works
- Click "Save Configuration" to persist
Code snippet (lines 1-50):
// API keys are stored in localStorage
const [config, setConfig] = useState<APIConfig>({
metaApiKey: '',
googleMapsApiKey: '',
googleMyBusinessApiKey: '',
tiktokApiKey: '',
backendScraperUrl: 'http://localhost:3001',
});
// Save to localStorage
const handleSave = () => {
saveAPIConfig(config);
// ...
};This file contains all the actual API integration code. Each platform has its own function.
Function: searchMetaBusinesses() (lines 50-100)
export async function searchMetaBusinesses(config: SearchConfig): Promise<ContactResult[]> {
const apiConfig = getAPIConfig();
// Make API call to Meta Graph API
const response = await fetch(
`https://graph.facebook.com/v18.0/pages/search?q=${encodeURIComponent(config.query)}&limit=${config.maxResults}&access_token=${apiConfig.metaApiKey}`
);
// Transform response to our format
const results = (data.data || []).map((page: any) => ({
id: `meta_${page.id}`,
businessName: page.name,
email: page.email || '',
phone: page.phone || '',
// ...
}));
return results;
}How to get Meta API key:
- Go to https://developers.facebook.com/
- Create a new app
- Add "Facebook Login" product
- Get your App ID and App Secret
- Generate an access token
Function: searchGoogleMaps() (lines 110-180)
export async function searchGoogleMaps(config: SearchConfig): Promise<ContactResult[]> {
const apiConfig = getAPIConfig();
// Text Search API
const searchResponse = await fetch(
`https://maps.googleapis.com/maps/api/place/textsearch/json?query=${encodeURIComponent(query)}&key=${apiConfig.googleMapsApiKey}`
);
// Get detailed information for each place
for (const place of searchData.results) {
const details = await getGooglePlaceDetails(place.place_id, apiConfig.googleMapsApiKey);
// Transform to our format
}
}How to get Google Maps API key:
- Go to https://console.cloud.google.com/
- Create a new project
- Enable "Places API" and "Maps JavaScript API"
- Go to "Credentials" β "Create Credentials" β "API Key"
- Copy the API key
Function: searchGoogleMyBusiness() (lines 190-240)
export async function searchGoogleMyBusiness(config: SearchConfig): Promise<ContactResult[]> {
const apiConfig = getAPIConfig();
// Note: GMB API requires OAuth 2.0 authentication
const response = await fetch(
`https://mybusiness.googleapis.com/v4/accounts/${config.query}?key=${apiConfig.googleMyBusinessApiKey}`
);
}How to get Google My Business API key:
- Go to https://developers.google.com/my-business
- Set up OAuth 2.0 credentials
- Request API access (requires approval)
- Get your API key
Function: searchTikTokBusinesses() (lines 250-300)
export async function searchTikTokBusinesses(config: SearchConfig): Promise<ContactResult[]> {
const apiConfig = getAPIConfig();
const response = await fetch(
`https://open.tiktokapis.com/v2/research/user/query/`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiConfig.tiktokApiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: { username: config.query },
fields: ['display_name', 'profile_description', 'is_verified'],
}),
}
);
}How to get TikTok API key:
- Go to https://developers.tiktok.com/
- Create a developer account
- Create a new app
- Request API access
- Get your access token
export async function searchAllSources(config: SearchConfig): Promise<ContactResult[]> {
const promises: Promise<ContactResult[]>[] = [];
// Call each API based on selected sources
if (config.sources.includes('meta')) {
promises.push(searchMetaBusinesses(config));
}
if (config.sources.includes('google_maps')) {
promises.push(searchGoogleMaps(config));
}
if (config.sources.includes('google_my_business')) {
promises.push(searchGoogleMyBusiness(config));
}
if (config.sources.includes('tiktok')) {
promises.push(searchTikTokBusinesses(config));
}
// Wait for all searches to complete
const resultsArrays = await Promise.all(promises);
// Flatten and deduplicate results
const allResults = resultsArrays.flat();
return uniqueResults;
}const handleSearch = useCallback(async () => {
if (!config.query.trim()) return;
setIsSearching(true);
// Check if API keys are configured
const apiConfig = getAPIConfig();
const hasAPIKeys = apiConfig.metaApiKey || apiConfig.googleMapsApiKey ||
apiConfig.googleMyBusinessApiKey || apiConfig.tiktokApiKey;
if (!hasAPIKeys) {
// Use mock data if no API keys configured
console.log('No API keys configured, using demo data');
// ... use mockResults
return;
}
// Use real API services
try {
const apiResults = await searchAllSources(config);
setResults(apiResults);
} catch (error) {
console.error('Search error:', error);
// Fallback to mock data on error
} finally {
setIsSearching(false);
}
}, [config]);User Input (Search Tab)
β
handleSearch() in App.tsx
β
Check if API keys exist (getAPIConfig())
β
βββββ΄ββββ
β β
NO API HAS API
β β
β β
Mock searchAllSources() in apiServices.ts
Data β
β βββββ΄ββββ¬ββββββββββββ¬βββββββββββ
β β β β β
β β β β β
β Meta Google Google TikTok
β API Maps GMB API
β β β β β
β βββββ¬ββββ΄ββββββββββββ΄βββββββββββ
β β
β Combine & Deduplicate Results
β β
βββββ¬ββββ
β
Display Results
// In src/types.ts
export interface ContactResult {
source: 'meta' | 'google_maps' | 'google_my_business' | 'tiktok' | 'new_source';
// ...
}
export interface SearchConfig {
sources: ('meta' | 'google_maps' | 'google_my_business' | 'tiktok' | 'new_source')[];
// ...
}// In src/apiServices.ts
export async function searchNewSource(config: SearchConfig): Promise<ContactResult[]> {
const apiConfig = getAPIConfig();
const response = await fetch('https://api.newsource.com/search', {
headers: {
'Authorization': `Bearer ${apiConfig.newSourceApiKey}`,
},
});
// Transform response
return results;
}// In searchAllSources() function
if (config.sources.includes('new_source')) {
promises.push(searchNewSource(config));
}// In src/SettingsPage.tsx
<div>
<label>New Source API Key</label>
<input
type="password"
value={config.newSourceApiKey}
onChange={e => setConfig(prev => ({ ...prev, newSourceApiKey: e.target.value }))}
/>
</div>// In src/App.tsx source selection section
{ id: 'new_source' as const, name: 'New Source', desc: 'Description', icon: NewIcon, color: 'purple' }- Location: Lines 320-490
- What it does: Provides search form UI
- API connection: Calls
handleSearch()which usessearchAllSources()
- Location: Entire file
- What it does: Scrapes websites directly
- API connection: Calls backend scraper service at
backendScraperUrl
- Location: Entire file
- What it does: Configure API keys
- API connection: Saves to localStorage, tests API keys
- Location: Lines 500-700
- What it does: Displays search results
- API connection: Receives data from
searchAllSources()
- Current: Browser localStorage
- Production: Environment variables or secure backend
// Instead of localStorage, use environment variables
const API_CONFIG = {
metaApiKey: import.meta.env.VITE_META_API_KEY,
googleMapsApiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
// ...
};For production, route API calls through your backend:
// Frontend calls your backend
const response = await fetch('/api/search/meta', {
method: 'POST',
body: JSON.stringify(config),
});
// Backend makes actual API call with secure keys
app.post('/api/search/meta', async (req, res) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/pages/search?access_token=${process.env.META_API_KEY}`
);
res.json(await response.json());
});| What | Where | File |
|---|---|---|
| Enter API keys | Settings tab | src/SettingsPage.tsx |
| API calls are made | apiServices.ts | src/apiServices.ts |
| Search is triggered | Search tab | src/App.tsx β handleSearch() |
| Results are displayed | Results tab | src/App.tsx β Results View |
| Website scraping | Web Scraper tab | src/WebsiteScraperView.tsx |
| API key storage | localStorage | src/apiServices.ts β saveAPIConfig() |
- Open the app β Click "Settings" in sidebar
- Add API keys β Enter keys for platforms you want to use
- Test keys β Click "Test Key" for each platform
- Save β Click "Save Configuration"
- Search β Go to "Search" tab and start searching
- View results β Results appear in "Results" tab
- Export β Download from "Export" tab
- Go to Settings tab
- Add at least one API key
- Click "Save Configuration"
- Check API key is correct
- Verify API key has proper permissions
- Check API quota/limits
- Review API documentation for your platform
- Verify API keys are working (test them)
- Check search query is valid
- Try different search terms
- Check API rate limits
- Make sure backend is running:
cd backend && npm start - Check backend URL in Settings matches your backend port
- Verify CORS is enabled on backend
- Meta Graph API Docs
- Google Places API Docs
- Google My Business API Docs
- TikTok for Developers
- SCRAPING_GUIDE.md - Detailed scraping techniques