Yext Account Service
๐ Overviewโ
The Yext Account service provides account-level operations for verifying entity initialization status. It checks whether a DashClicks account has been linked to a Yext entity/location and retrieves account information. This service is used as a dependency by other Yext services to validate account status before performing operations.
Source File: external/Integrations/Yext/services/account.service.js
External API: Yext Accounts API
Primary Use: Verify account entity initialization and retrieve account data
๐๏ธ Collections Usedโ
accountโ
- Operations: Read
- Model:
external/models/account.js - Usage Context: Check if account has Yext entity initialized
- Key Fields:
yext.entity- Yext entity/location ID (string)
๐ Data Flowโ
sequenceDiagram
participant Service as Calling Service
participant AccountService as Account Service
participant AccountDB as Account Collection
participant YextAPI as Yext API
Service->>AccountService: find(accountId)
AccountService->>AccountDB: findById(accountId)
alt Account has yext.entity
AccountDB-->>AccountService: Return account with entity
AccountService-->>Service: Return entity ID
else No yext field or empty entity
AccountDB-->>AccountService: Account without entity
AccountService-->>Service: Return error object
end
Service->>AccountService: list() - Get Yext accounts
AccountService->>AccountService: Verify account initialized
AccountService->>YextAPI: GET /accounts
YextAPI-->>AccountService: Accounts list
AccountService-->>Service: Return accounts
style AccountService fill:#e3f2fd
style YextAPI fill:#fff4e6
๐ง Business Logic & Functionsโ
find(accountID)โ
Purpose: Check if account has Yext entity initialized and return entity ID or error
Source: services/account.service.js
Parameters:
accountID(ObjectId) - DashClicks account ID
Returns: Promise<String | Object>
- Success: Returns entity ID as string
- Error: Returns error object with
{ error: true, message: String }
Business Logic Flow:
-
Fetch Account
const query = await Account.findById(accountID).lean().exec(); -
Check Entity Initialization
if (query) {
if (query.yext && query.yext.entity != '') {
return Promise.resolve(query.yext.entity);
} else {
return Promise.resolve({
error: true,
message: 'Listings not initialized for this account.',
});
}
} else {
return Promise.resolve({
error: true,
message: 'Record not found',
});
}
Return Values:
// Success - Entity initialized
("12345678"); // Yext entity ID string
// Error - Entity not initialized
{
error: true,
message: "Listings not initialized for this account."
}
// Error - Account not found
{
error: true,
message: "Record not found"
}
Example Usage:
const result = await accountService.find(accountId);
if (result?.error) {
console.error('Account error:', result.message);
// Handle: entity not initialized or account not found
} else {
const entityId = result;
console.log('Entity ID:', entityId);
// Proceed with entity operations
}
Key Business Rules:
- String Check: Checks
query.yext.entity != ''(empty string = not initialized) - Error Object Pattern: Returns object with
error: trueinstead of throwing - Lean Query: Uses
.lean()for better performance (returns plain object) - Promise Wrapped: Always returns Promise.resolve() for consistency
getAccount(accountId)โ
Purpose: Retrieve complete account document from database
Source: services/account.service.js
Parameters:
accountId(ObjectId) - DashClicks account ID
Returns: Promise<Object | null> - Complete account document or null
Business Logic Flow:
const account = await Account.findById(accountId).lean().exec();
return account;
Return Value:
// Account exists
{
_id: ObjectId("507f1f77bcf86cd799439011"),
name: "Business Name",
email: "contact@example.com",
yext: {
entity: "12345678"
},
yext_status: true,
// ... other account fields
}
// Account not found
null
Example Usage:
const account = await accountService.getAccount(accountId);
if (!account) {
throw notFound('Account not found');
}
console.log('Account name:', account.name);
console.log('Yext entity:', account.yext?.entity);
console.log('Yext status:', account.yext_status);
Key Business Rules:
- Returns Full Document: Unlike
find(), returns complete account object - Returns Null: Returns null if account not found (doesn't throw or return error object)
- Lean Query: Uses
.lean()for performance - No Validation: Doesn't check yext initialization status
list({ query, body, accountId })โ
Purpose: List Yext accounts accessible with API key
Source: services/account.service.js
External API Endpoint: GET https://api.yext.com/v2/accounts
Parameters:
query(Object) - Query parameters for Yext APIbody(Object) - Request body (unused in GET)accountId(ObjectId) - DashClicks account ID
Returns: Promise<Object> - Yext accounts list
Business Logic Flow:
-
Verify Account Initialization
const account = await exports.find(accountId);
if (account?.error) {
throw notFound(account?.message);
} -
Fetch Yext Accounts
const v = process.env.YEXT_API_VPARAM || '20200525';
const url = 'https://api.yext.com/v2/accounts?' + querystring.encode({ v: v });
const options = {
method: 'GET',
headers: { 'api-key': process.env.YEXT_API_KEYS },
data: body,
params: query,
url,
};
const dns = await axios(options);
return dns.data;
API Request Example:
GET https://api.yext.com/v2/accounts?v=20200525
Headers:
api-key: {YEXT_API_KEY}
API Response Example:
{
"meta": {
"uuid": "abc-def-123",
"errors": []
},
"response": {
"count": 3,
"accounts": [
{
"id": "me",
"accountId": "12345",
"accountName": "Main Account",
"countryCode": "US"
},
{
"id": "sub_account_1",
"accountId": "67890",
"accountName": "Sub Account 1",
"parentAccountId": "12345"
}
]
}
}
Error Handling:
- Account Not Initialized: Throws 404 Not Found with message from
find() - API Errors: Yext API errors propagate up
Example Usage:
const accounts = await accountService.list({
accountId: '507f1f77bcf86cd799439011',
query: { v: '20200525' },
body: {},
});
console.log('Yext accounts:', accounts.response.accounts);
Key Business Rules:
- Requires Initialization: Must have entity initialized before listing accounts
- API Key Scope: Returns accounts accessible with provided API key
- Includes Sub-accounts: May include parent and sub-accounts
- Validation Before API Call: Checks account status before making external API call
๐ Integration Pointsโ
Used By Other Servicesโ
The account service is a dependency for most Yext services:
Entities Service:
const account = await accountService.find(accountId);
if (account?.error) {
throw notFound(account?.message);
}
// Proceed with entity operations
Categories Service:
const account = await accountService.find(accountId);
if (account?.error) {
throw notFound('Record not found.');
}
// Fetch categories
Publishers Service:
const account = await accountService.find(accountId);
if (account?.error) {
throw notFound(account?.message);
}
// Fetch publishers
Typical Usage Patternโ
// Standard pattern used across Yext services
async function someYextOperation({ accountId, ...params }) {
// 1. Verify account has entity
const account = await accountService.find(accountId);
// 2. Check for error
if (account?.error) {
throw notFound(account?.message);
}
// 3. Proceed with operation using entity ID
const entityId = account; // account is the entity ID string
// ... make Yext API calls
}
๐งช Edge Cases & Special Handlingโ
Account Exists But No Entityโ
Issue: Account document exists but doesn't have yext field or yext.entity is empty
Handling: Returns error object
{
error: true,
message: "Listings not initialized for this account."
}
Solution: Create entity using entitiesService.create()
Account Not Foundโ
Issue: Account ID doesn't exist in database
Handling: Returns error object
{
error: true,
message: "Record not found"
}
Solution: Verify account ID is correct
Empty String Entityโ
Issue: yext.entity field exists but is empty string ""
Handling: Treated as not initialized
if (query.yext.entity != '') {
// Only returns entity if not empty string
}
Why: Empty string indicates incomplete initialization
โ ๏ธ Important Notesโ
- Error Object Pattern:
find()returns error object, doesn't throw - Dual Return Type: Returns string (success) or object (error)
- Empty String Check: Uses
!= ''to validate entity initialization - Lean Queries: All queries use
.lean()for performance - No Throwing in find():
find()never throws, always returns Promise - getAccount() vs find():
getAccount()returns full document,find()returns entity ID or error - list() Requires Init:
list()throws if account not initialized - Dependency Service: Primary purpose is validation for other services
- No Caching: Queries database on every call
- API Versioning:
list()includesvparameter for Yext API
๐ Related Documentationโ
- Yext Integration Overview: index.md
- Entities Service: entities.md - Creates and manages entities
- Yext Accounts API: https://developer.yext.com/docs/api-reference/accounts/
- Account Model:
external/models/account.js
๐ฏ Service Purpose Summaryโ
The account service serves as a gatekeeper for Yext operations:
- โ Validation: Ensures account has entity before operations
- โ Abstraction: Provides consistent error handling pattern
- โ Dependency: Used by all other Yext services
- โ Simple API: Three clear methods with specific purposes
When to use each method:
find(accountId)- Check if entity initialized (returns entity ID or error)getAccount(accountId)- Get full account documentlist({ accountId, query, body })- List Yext accounts (requires initialization)