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โ
google-ads-tokenโ
- 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:
-
Extract OAuth Token
const accessToken = req.access_token; -
Call MCC Model
const mccModel = new MccModel(accessToken);
const managers = await mccModel.getManagers(); -
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); -
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
} -
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:
-
Validate Parameters
if (!managerID) {
throw new Error('Please provide managerID');
} -
Call MCC Model
const mccModel = new MccModel(accessToken, managerID, clientID);
const customers = await mccModel.getCustomers(); -
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}` : ''}
`; -
Execute Query
const response = await googleAdsClient.query(managerID, query); -
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,
})); -
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-idrequired for manager operations
UI Integrationโ
Typical Flow:
- User authenticates (OAuth)
- Call
getManagers()to list accessible managers - User selects manager account
- Call
getCustomers(managerID)to list clients - User selects client
- Make campaign/ad group/keyword requests with
clientIDandmanagerID
๐งช Edge Cases & Special Handlingโ
Manager vs Client Accountsโ
Issue: User may have both manager and client accounts
Handling:
- Filter accounts by
is_managerflag - 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
managerIDandclientID
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)
๐ Related Documentationโ
- Integration Overview: Google Ads Integration
- Authentication: OAuth Flow
- Campaigns: Campaign Management
- Google Ads MCC Docs: Manager Accounts
- GAQL Reference: Google Ads Query Language
๐ฏ 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
managerIDandclientIDparameters - Use
login-customer-idheader set to manager ID - Format customer IDs without hyphens
- Handle empty result sets gracefully