Yext Integration
🎯 Overview
The Yext integration enables DashClicks to manage business listings across 150+ directories and publisher platforms (Google, Facebook, Yelp, etc.) through Yext's Business Listings API. It provides entity creation, listing optimization, publisher management, and duplicate listing scan capabilities.
Provider: Yext (https://www.yext.com)
API Version: v2
API Versioning: Uses v parameter (default: 20200525)
Integration Type: REST API with API Key authentication
📁 Directory Structure
Documentation Structure:
yext/
├── 📄 index.md - Yext integration overview and setup
├── 📄 entities.md - Business entity management (CRUD operations)
├── 📄 account.md - Account verification and listing initialization
├── 📄 categories.md - Business category management
├── 📄 publishers.md - Publisher directory listing
├── 📄 optimization.md - Listing optimization tasks and links
└── 📄 scan.md - Duplicate listing detection and monitoring
Source Code Location:
- Base Path:
external/Integrations/Yext/ - Services:
services/(6 service files) - Controllers:
Controllers/ - Models:
external/models/(yext-specific)
🗄️ MongoDB Collections
📚 Detailed Schema: See Database Collections Documentation
account
- Purpose: Store Yext entity ID for DashClicks accounts
- Model:
external/models/account.js - Primary Use: Link DashClicks accounts to Yext business entities
- Key Fields:
yext.entity- Yext entity ID (location ID)yext_status- Yext service activation status
yext-publishers-logo
- Purpose: Store publisher directory logos
- Model:
external/models/yext-publishers-logo.js - Primary Use: Display publisher logos in listing reports
- Key Fields:
publisherId- Publisher ID from Yextlogo- Logo image URL
yext-scans
- Purpose: Store duplicate listing scan results
- Model:
external/models/yext-scans.js - Primary Use: Cache scan data and monitor duplicate listings
- Key Fields:
account_id- DashClicks account IDscan_data.jobId- Yext scan job IDscan_data.sites- Array of detected listingsbusiness_info- Business data used for scan
- TTL: Documents expire automatically (expiresAt field)
🔐 Authentication & Configuration
Authentication Method: API Key (Header-based)
Required Environment Variables:
| Variable | Description | Required |
|---|---|---|
YEXT_API_KEYS | Primary Yext API key | ✅ |
YEXT_API_KEY_SCAN | Dedicated API key for scan service | ✅ |
YEXT_API_VPARAM | API version parameter (default: 20200525) | ❌ |
Authentication Pattern:
// All API requests include api-key header
headers: {
'api-key': process.env.YEXT_API_KEYS
}
API Versioning:
All Yext API endpoints require a v query parameter for versioning:
const v = process.env.YEXT_API_VPARAM || '20200525';
// Example request
axios({
url: 'https://api.yext.com/v2/accounts/me/entities',
params: { v: v },
headers: { 'api-key': process.env.YEXT_API_KEYS },
});
🏗️ Architecture Overview
Key Responsibilities:
- Entity Management: Create, update, delete business entities (locations)
- Listing Distribution: Activate listings to 150+ publisher directories
- Optimization: Manage listing optimization tasks for better visibility
- Duplicate Detection: Scan for duplicate listings across the web
- Publisher Management: List available publisher directories
- Category Management: Manage business category classifications
- Analytics: Generate reports on listing performance
API Communication Pattern:
- REST API with JSON requests/responses
- Header-based API key authentication
- Query parameter API versioning (
v=20200525) - Synchronous request/response for most operations
- Asynchronous job-based processing for scans
Rate Limiting:
- Yext enforces rate limits per API key (specific limits not documented in code)
- No explicit rate limiting handling implemented
- Recommendation: Implement retry logic with exponential backoff
Business Logic Flow:
graph TB
A[DashClicks Account] -->|Create Entity| B[Yext Entity/Location]
B -->|Save entity ID| C[account.yext.entity]
B -->|Activate Service| D[SKU: LC-00000019]
D -->|Distribute to| E[150+ Publishers]
E -->|Google, Facebook, Yelp, etc| F[Live Listings]
F -->|Monitor| G[Optimization Tasks]
F -->|Detect Duplicates| H[Yext Scan Service]
🔗 Features & Capabilities
Core Features
- 📘 Entities - CRUD operations for business entities/locations
- 📗 Account - Account verification and entity initialization
- 📙 Categories - Business category listing
- 📕 Publishers - Publisher directory management
- 📓 Optimization - Listing optimization tasks and links
- 📔 Scan - Duplicate listing detection
🔄 Integration Data Flow
Entity Creation and Activation
sequenceDiagram
participant DC as DashClicks API
participant YextService as Yext Service
participant AccountDB as Account Collection
participant YextAPI as Yext API
DC->>YextService: Create entity (business data)
YextService->>AccountDB: Check existing entity
AccountDB-->>YextService: No entity found
YextService->>YextAPI: POST /entities
Note over YextService,YextAPI: Headers: api-key<br/>Body: Business info
YextAPI-->>YextService: Entity created (meta.id)
YextService->>AccountDB: Save entity ID
Note over AccountDB: account.yext.entity = entityId
YextService->>YextAPI: POST /existinglocationaddrequests
Note over YextService,YextAPI: Activate SKU: LC-00000019
YextAPI-->>YextService: Service activated
YextService-->>DC: Entity created and activated
style YextService fill:#e3f2fd
style YextAPI fill:#fff4e6
Listing Scan Flow
sequenceDiagram
participant DC as DashClicks API
participant ScanService as Scan Service
participant ScanDB as YextScan Collection
participant YextAPI as Yext Scan API
DC->>ScanService: Get scan results
ScanService->>ScanDB: Find existing scan
alt Scan exists
ScanDB-->>ScanService: Return cached jobId
ScanService->>YextAPI: GET /scan/:jobId/:sites
YextAPI-->>ScanService: Scan results
ScanService->>ScanDB: Update cached results
else No scan or expired
ScanService->>YextAPI: POST /scan (create new)
YextAPI-->>ScanService: jobId + sites
ScanService->>YextAPI: GET /scan/:jobId/:sites
YextAPI-->>ScanService: Scan results
ScanService->>ScanDB: Cache new scan
end
ScanService-->>DC: Return scan results with logos
style ScanService fill:#e3f2fd
style YextAPI fill:#fff4e6
🔗 Submodules
- Entities Service - Complete CRUD operations for business entities
- Account Service - Account verification and entity status checks
- Categories Service - List available business categories
- Publishers Service - List available publisher directories
- Optimization Service - Manage listing optimization tasks
- Scan Service - Detect and monitor duplicate listings
🚨 Error Handling
Common Error Scenarios:
-
Entity Not Initialized
- Error: "Listings not initialized for this account."
- Cause: Account doesn't have
yext.entityfield - Solution: Create entity first using entities service
-
Entity ID Mismatch
- Error: "Entity Id mismatch!"
- Cause: Provided entity ID doesn't match account's stored entity
- Solution: Verify entity ownership before operations
-
Invalid API Key
- Status: 401 Unauthorized
- Cause: Missing or invalid YEXT_API_KEYS
- Solution: Check environment variables
-
Optimization Not Eligible
- Error: "User not eligible for the optimization task(s)."
- Cause: Entity doesn't have active optimization tasks
- Solution: Check entity status and active services
📊 Monitoring & Logging
- Scan Service: Uses logger utility for error tracking
- Error Logging: Errors logged with context (initiator, error, message)
- No Metrics: No explicit metrics collection implemented
🔗 Related Documentation
- Yext API Documentation: https://developer.yext.com/docs/
- Yext Entities API: https://developer.yext.com/docs/api-reference/entities/
- Yext Listings API: https://developer.yext.com/docs/api-reference/listings/
- Yext Scan API: https://developer.yext.com/docs/api-reference/scan/
- Account Model:
external/models/account.js - Yext Models:
external/models/yext-*.js
⚠️ Important Integration Notes
- API Versioning: All requests must include
vparameter (default: 20200525) - Service Activation: After entity creation, must activate with SKU: LC-00000019
- Entity Verification: All operations verify entity ID matches account before proceeding
- Separate API Keys: Scan service uses dedicated API key (YEXT_API_KEY_SCAN)
- Scan Caching: Scan results cached in MongoDB with TTL expiration
- Publisher Logos: Logos stored separately and joined to listing data
- Account Dependency: Most operations require account to have
yext.entityset - No Rate Limiting: No explicit rate limit handling - relies on Yext's limits
- Error Handling: Account/entity errors return structured error objects
- Optimization Links: Redirect URL required for optimization task links
🔧 Quick Start Examples
Create and Activate Entity
// 1. Create entity
const entity = await entitiesService.create({
accountId: '507f1f77bcf86cd799439011',
body: {
name: 'My Business',
address: {
line1: '123 Main St',
city: 'New York',
region: 'NY',
postalCode: '10001',
},
phone: '+1-555-0100',
},
query: { v: '20200525' },
});
// Entity automatically:
// - Saved to account.yext.entity
// - Activated with SKU LC-00000019
Get Listing Status
// Check if account has entity
const entityId = await accountService.find(accountId);
if (entityId.error) {
console.log('Listings not initialized');
} else {
// Get listings by location
const listings = await entitiesService.listListingsByLocation({
accountId: accountId,
params: { entityId: entityId, v: '20200525' },
});
}
Scan for Duplicates
// Scan for duplicate listings
const scan = await scanService.getScan(accountId, {
name: 'My Business',
address: '123 Main St, New York, NY 10001',
phone: '+1-555-0100',
});
console.log('Scan Job ID:', scan.scan_data.jobId);
console.log('Detected Listings:', scan.scan_data.sites.length);