Skip to main content

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:

  1. Fetch Account

    const query = await Account.findById(accountID).lean().exec();
  2. 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: true instead 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 API
  • body (Object) - Request body (unused in GET)
  • accountId (ObjectId) - DashClicks account ID

Returns: Promise<Object> - Yext accounts list

Business Logic Flow:

  1. Verify Account Initialization

    const account = await exports.find(accountId);

    if (account?.error) {
    throw notFound(account?.message);
    }
  2. 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โ€‹

  1. Error Object Pattern: find() returns error object, doesn't throw
  2. Dual Return Type: Returns string (success) or object (error)
  3. Empty String Check: Uses != '' to validate entity initialization
  4. Lean Queries: All queries use .lean() for performance
  5. No Throwing in find(): find() never throws, always returns Promise
  6. getAccount() vs find(): getAccount() returns full document, find() returns entity ID or error
  7. list() Requires Init: list() throws if account not initialized
  8. Dependency Service: Primary purpose is validation for other services
  9. No Caching: Queries database on every call
  10. API Versioning: list() includes v parameter for Yext API

๐ŸŽฏ 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 document
  • list({ accountId, query, body }) - List Yext accounts (requires initialization)
๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM