Skip to main content

Google Ads - MCC Operations

๐Ÿ“– Overviewโ€‹

The MCC (My Client Center) operations module enables management of Google Ads manager accounts and their associated client accounts. It provides functionality to list accessible manager accounts and retrieve clients under a specific manager, essential for agencies managing multiple advertisers.

Source Files:

  • Controller: external/Integrations/GoogleAds/Controllers/Mcc/MccController.js
  • Model: external/Integrations/GoogleAds/Models/Mcc/MccModel.js
  • Routes: external/Integrations/GoogleAds/Routes/mcc.js

External API: Google Ads API Customer Service

๐Ÿ—„๏ธ Collections Usedโ€‹

  • Operations: Read
  • Model: external/Integrations/GoogleAds/Models/token.js
  • Usage Context: Fetch OAuth tokens for API authentication

๐Ÿ”„ Data Flowโ€‹

Manager Account Listing Flowโ€‹

sequenceDiagram
participant Client
participant MccController
participant MccModel
participant GoogleAdsAPI

Client->>MccController: GET /mcc/managers
MccController->>MccModel: getManagers(access_token)
MccModel->>GoogleAdsAPI: List accessible customers
GoogleAdsAPI-->>MccModel: Customer list
MccModel->>MccModel: Filter manager accounts
MccModel-->>MccController: Manager account list
MccController-->>Client: JSON response with managers

Client Account Listing Flowโ€‹

sequenceDiagram
participant Client
participant MccController
participant MccModel
participant GoogleAdsAPI

Client->>MccController: GET /mcc/customers?managerID
MccController->>MccModel: getCustomers(managerID)
MccModel->>GoogleAdsAPI: List customer clients
GoogleAdsAPI-->>MccModel: Client list
MccModel->>MccModel: Format client data
MccModel-->>MccController: Client account list
MccController-->>Client: JSON response with clients

๐Ÿ”ง Business Logic & Functionsโ€‹

getManagers()โ€‹

Purpose: Retrieve all accessible manager accounts for the authenticated user

Source: Controllers/Mcc/MccController.js โ†’ Models/Mcc/MccModel.js

External API Endpoint: GET https://googleads.googleapis.com/v{version}/customers:listAccessibleCustomers

Parameters:

  • None (uses OAuth token from request)

Returns: JSON Array

{
success: true,
message: "SUCCESS",
data: [
{
id: "1234567890",
name: "Manager Account Name",
descriptive_name: "My Marketing Agency",
currency_code: "USD",
time_zone: "America/New_York",
is_manager: true,
can_manage_clients: true,
test_account: false
},
// ... more managers
]
}

Business Logic Flow:

  1. Extract OAuth Token

    const accessToken = req.access_token;
  2. Call MCC Model

    const mccModel = new MccModel(accessToken);
    const managers = await mccModel.getManagers();
  3. API Request (in MccModel)

    // List all accessible customers
    const response = await googleAdsClient.listAccessibleCustomers();

    // Filter for manager accounts only
    const managers = response.resource_names
    .map(resourceName => {
    const customerId = resourceName.split('/')[1];
    return {
    customer_id: customerId,
    resource_name: resourceName,
    };
    })
    .filter(customer => customer.is_manager === true);
  4. Fetch Manager Details

    // For each manager, fetch full details
    for (const manager of managers) {
    const customerData = await googleAdsClient.customers.get(manager.customer_id);
    manager.descriptive_name = customerData.descriptive_name;
    manager.currency_code = customerData.currency_code;
    manager.time_zone = customerData.time_zone;
    // ... other fields
    }
  5. Return Formatted Data

    • Returns array of manager account objects
    • Includes account metadata
    • Sorted by descriptive name

API Request Example:

GET https://googleads.googleapis.com/v15/customers:listAccessibleCustomers
Headers:
Authorization: Bearer {access_token}
developer-token: {GOOGLE_ADS_DEVELOPER_TOKEN}

API Response Example:

{
resource_names: ['customers/1234567890', 'customers/9876543210'];
}

Error Handling:

  • 401 Unauthorized: Invalid or expired OAuth token
  • 403 Forbidden: Developer token not approved
  • 404 Not Found: No accessible accounts
  • 500 Internal Error: Google API error

Example Usage:

// Get all manager accounts
GET /v1/e/google/ads/mcc/managers

// Response
{
success: true,
message: "SUCCESS",
data: [
{
id: "1234567890",
name: "My Agency MCC",
is_manager: true
}
]
}

Use Cases:

  • Display list of manager accounts in UI
  • Allow user to select which manager to use
  • Verify user has manager account access
  • Agency dashboard showing all managed accounts

Side Effects:

  • โš ๏ธ External API call to Google Ads
  • โš ๏ธ Multiple API calls (one per manager for details)
  • โš ๏ธ Quota usage for customer listing

getCustomers()โ€‹

Purpose: Retrieve all client accounts under a specific manager account

Source: Controllers/Mcc/MccController.js โ†’ Models/Mcc/MccModel.js

External API Endpoint: POST https://googleads.googleapis.com/v{version}/customers/{manager_id}/googleAds:searchStream

Parameters:

  • managerID (String, Required) - Manager account customer ID (without hyphens)
  • clientID (String, Optional) - Specific client ID to fetch

Returns: JSON Array

{
success: true,
message: "SUCCESS",
data: [
{
client_id: "9876543210",
client_name: "Client Company Name",
client_descriptive_name: "Client Ads Account",
currency_code: "USD",
time_zone: "America/Los_Angeles",
status: "ENABLED",
manager: {
manager_id: "1234567890",
manager_name: "Agency MCC"
},
test_account: false,
hidden: false
},
// ... more clients
]
}

Business Logic Flow:

  1. Validate Parameters

    if (!managerID) {
    throw new Error('Please provide managerID');
    }
  2. Call MCC Model

    const mccModel = new MccModel(accessToken, managerID, clientID);
    const customers = await mccModel.getCustomers();
  3. Build GAQL Query (Google Ads Query Language)

    const query = `
    SELECT
    customer_client.id,
    customer_client.descriptive_name,
    customer_client.currency_code,
    customer_client.time_zone,
    customer_client.status,
    customer_client.manager,
    customer_client.test_account,
    customer_client.hidden
    FROM customer_client
    WHERE customer_client.manager = FALSE
    ${clientID ? `AND customer_client.id = ${clientID}` : ''}
    `;
  4. Execute Query

    const response = await googleAdsClient.query(managerID, query);
  5. Format Response

    const customers = response.results.map(row => ({
    client_id: row.customer_client.id,
    client_name: row.customer_client.descriptive_name,
    currency_code: row.customer_client.currency_code,
    time_zone: row.customer_client.time_zone,
    status: row.customer_client.status,
    test_account: row.customer_client.test_account,
    hidden: row.customer_client.hidden,
    }));
  6. Return Filtered Data

    • Excludes hidden accounts
    • Filters by status if specified
    • Sorts by descriptive name

API Request Example:

POST https://googleads.googleapis.com/v15/customers/1234567890/googleAds:searchStream
Headers:
Authorization: Bearer {access_token}
developer-token: {GOOGLE_ADS_DEVELOPER_TOKEN}
login-customer-id: 1234567890
Body: {
query: "SELECT customer_client.id, customer_client.descriptive_name FROM customer_client WHERE customer_client.manager = FALSE"
}

API Response Example:

{
results: [
{
customer_client: {
id: 9876543210,
resource_name: 'customers/1234567890/customerClients/9876543210',
descriptive_name: 'Client Account',
currency_code: 'USD',
time_zone: 'America/Los_Angeles',
status: 'ENABLED',
manager: false,
test_account: false,
hidden: false,
},
},
];
}

Error Handling:

  • 400 Missing managerID: Returns error message
  • 401 Unauthorized: Invalid OAuth token
  • 403 Forbidden: No access to manager account
  • 404 Not Found: Manager account doesn't exist
  • 500 Query Error: GAQL syntax error or API failure

Example Usage:

// Get all clients under manager
GET /v1/e/google/ads/mcc/customers?managerID=1234567890

// Get specific client
GET /v1/e/google/ads/mcc/customers
?managerID=1234567890
&clientID=9876543210

// Response
{
success: true,
message: "SUCCESS",
data: [
{
client_id: "9876543210",
client_name: "My Client Account",
currency_code: "USD",
status: "ENABLED"
}
]
}

Use Cases:

  • Display list of clients in agency dashboard
  • Select client for campaign management
  • Validate client access permissions
  • Multi-client reporting setup

Side Effects:

  • โš ๏ธ External API call to Google Ads
  • โš ๏ธ GAQL query execution (quota usage)
  • โš ๏ธ May return large result sets (pagination not implemented in this endpoint)

๐Ÿ”€ Integration Pointsโ€‹

Internal Servicesโ€‹

  • Campaign Management: Uses MCC to select client before fetching campaigns
  • Ad Group Operations: Requires client selection via MCC
  • Keyword Management: Client context needed from MCC
  • Reporting: Multi-client reports use MCC data

API Dependenciesโ€‹

  • Resource: Google Ads Customer Service
  • Query Language: GAQL (Google Ads Query Language)
  • Authentication: OAuth 2.0 Bearer token + Developer token
  • Header: login-customer-id required for manager operations

UI Integrationโ€‹

Typical Flow:

  1. User authenticates (OAuth)
  2. Call getManagers() to list accessible managers
  3. User selects manager account
  4. Call getCustomers(managerID) to list clients
  5. User selects client
  6. Make campaign/ad group/keyword requests with clientID and managerID

๐Ÿงช Edge Cases & Special Handlingโ€‹

Manager vs Client Accountsโ€‹

Issue: User may have both manager and client accounts
Handling:

  • Filter accounts by is_manager flag
  • Separate endpoints for managers vs clients
  • UI should clearly indicate account type

Test Accountsโ€‹

Issue: Test accounts mixed with production accounts
Detection:

customer.test_account === true;

Handling:

  • Flag test accounts in response
  • UI can filter/badge test accounts
  • Prevents accidental production operations on test accounts

Hidden Accountsโ€‹

Issue: Clients may be hidden in manager account
Handling:

WHERE customer_client.hidden = FALSE
  • Exclude hidden accounts from default listing
  • Optional parameter to include hidden accounts

No Manager Accessโ€‹

Issue: User has client account but no manager account
Handling:

  • getManagers() returns empty array
  • Allow direct client operations without manager
  • Use client ID as both managerID and clientID

Customer ID Formatโ€‹

Issue: Google uses both with and without hyphens
Format Examples:

  • With hyphens: 123-456-7890
  • Without hyphens: 1234567890

Handling:

// Always remove hyphens for API calls
const cleanCustomerId = customerId.replace(/-/g, '');

โš ๏ธ Important Notesโ€‹

  • ๐Ÿ” Manager Access: Requires manager account to list clients
  • ๐Ÿ’ฐ Quota Usage: Each API call counts against quota
  • โฑ๏ธ Rate Limits: Subject to Google Ads API rate limits
  • ๐Ÿ”„ Account Hierarchy: Manager โ†’ Client โ†’ Campaign โ†’ Ad Group
  • ๐Ÿ“ GAQL: Uses Google Ads Query Language for filtering
  • ๐Ÿšจ Login Customer ID: Header required for cross-account access
  • ๐Ÿ”— Resource Names: Full resource paths returned in responses
  • ๐ŸŽฏ Filtering: Can filter by test accounts, hidden status

๐Ÿ“Š MCC Account Hierarchyโ€‹

Manager Account (MCC)
โ”œโ”€โ”€ Client Account 1
โ”‚ โ”œโ”€โ”€ Campaign 1-A
โ”‚ โ”œโ”€โ”€ Campaign 1-B
โ”‚ โ””โ”€โ”€ Campaign 1-C
โ”œโ”€โ”€ Client Account 2
โ”‚ โ”œโ”€โ”€ Campaign 2-A
โ”‚ โ””โ”€โ”€ Campaign 2-B
โ””โ”€โ”€ Client Account 3
โ””โ”€โ”€ Campaign 3-A

Hierarchy Rules:

  • One manager can have multiple clients
  • One client can have multiple managers
  • Campaigns belong to single client
  • Manager can't directly manage campaigns (must select client)


๐ŸŽฏ MCC Operations Checklistโ€‹

Before Using:

  • Verify OAuth token has manager account access
  • Confirm developer token approved
  • Understand manager vs client distinction

When Listing:

  • Call getManagers() first to get manager accounts
  • Store selected manager ID for subsequent calls
  • Call getCustomers(managerID) to list clients under manager
  • Store selected client ID for campaign operations

For API Requests:

  • Always provide both managerID and clientID parameters
  • Use login-customer-id header set to manager ID
  • Format customer IDs without hyphens
  • Handle empty result sets gracefully
๐Ÿ’ฌ

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:30 AM