Skip to main content

📊 TikTok Ads - Campaigns & Analytics

📖 Overview

The campaigns and analytics module provides comprehensive access to TikTok advertising campaigns, ad groups, individual ads, and integrated performance reports. Supports listing operations with pagination and advanced analytics reporting with custom dimensions, metrics, and filtering.

Source Files:

  • Controller: external/Integrations/TikTok/Controllers/analytics.js
  • Route: external/Integrations/TikTok/Routes/analytics.js
  • Provider: external/Integrations/TikTok/providers/tiktok-analytics.js
  • Constants: external/Integrations/TikTok/constants/constants.js

External API: TikTok Marketing API - Campaign Management & Integrated Reporting

🗄️ Collections Used

tiktok.tokens

  • Operations: Read
  • Model: shared/models/tik-tok-token.js
  • Usage Context: Retrieve access token for API authentication

analytics_tiktokanalytics_userconfigs

  • Operations: Read
  • Model: external/models/analytics-tiktokanalytics-userconfig.js
  • Usage Context: Retrieve selected advertiser ID for all operations

🔄 Data Flow

sequenceDiagram
participant Client as DashClicks App
participant Controller as Analytics Controller
participant Keys as Keys Model
participant Provider as TikTok Provider
participant TikTok as TikTok Marketing API

Client->>Controller: GET /campaigns?limit=10&page=1
Controller->>Keys: Find token + advertiser config
Keys-->>Controller: Access token + advertiser_id
Controller->>Provider: getCampaignsList()
Provider->>TikTok: GET /campaign/get?advertiser_id=...
TikTok-->>Provider: Campaigns + page_info
Provider-->>Controller: Response data
Controller-->>Client: Campaigns with pagination

🔧 Campaign Management Functions

List Campaigns

campaigns(req, res, next)

Purpose: Retrieve paginated list of advertising campaigns for the configured advertiser account

Source: Controllers/analytics.js

External API Endpoint: GET https://business-api.tiktok.com/v1.3/campaign/get

Request:

GET /v1/integrations/tiktok/campaigns?limit=10&page=1&campaign_ids=123,456&status=CAMPAIGN_STATUS_ENABLE
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescription
limitNumberResults per page (becomes page_size in API)
pageNumberPage number (1-based, default: 1)
campaign_idsStringComma-separated campaign IDs to filter
statusStringCampaign status filter (e.g., CAMPAIGN_STATUS_ENABLE)

Returns: Promise<Object>

Business Logic Flow:

  1. Validate Account & Extract Config

    • Call checkAccountAccess(req) to get account ID
    • Fetch OAuth token via keysModel.find(accountId)
    • Returns error if KEYS_NOT_FOUND
    • Extract advertiser_id from existKeys.configData
  2. Build Query Parameters

    • Set default page = 1 if not provided
    • If limit provided, add page_size: limit to query params
    • Merge all request query parameters
    • Add advertiser_id from config
  3. Call TikTok Campaigns API

    • Provider Function: tiktokAnalyticsProvider.getCampaignsList()
    • HTTP Method: GET
    • URL: {TIKTOK_BASE_URL}/{TIKTOK_VERSION}/campaign/get
    • Headers: Access-Token: {access_token}
    • Query Params: { advertiser_id, page_size, page, ...filters }
  4. Generate Pagination Metadata

    • Extract total_number from response page_info
    • Call utilities.generatePagination(limit, page, totalRecords)
    • Returns pagination object with total pages, current page, etc.
  5. Return Response

    • Campaign list from campaignsList.data.list
    • Pagination metadata

API Request Example:

GET https://business-api.tiktok.com/v1.3/campaign/get?advertiser_id=1234567890&page_size=10&page=1
Headers:
Access-Token: act.1234567890abcdef...

API Response Example:

{
"code": 0,
"message": "OK",
"data": {
"list": [
{
"campaign_id": "123456",
"campaign_name": "Summer Sale Campaign",
"advertiser_id": "1234567890",
"objective_type": "TRAFFIC",
"status": "CAMPAIGN_STATUS_ENABLE",
"budget": 1000.00,
"budget_mode": "BUDGET_MODE_DAY",
"create_time": "2025-09-01 10:00:00",
"modify_time": "2025-10-01 15:30:00"
}
],
"page_info": {
"total_number": 45,
"page": 1,
"page_size": 10
}
}
}

Success Response:

{
"success": true,
"message": "SUCCESS",
"data": [
{
"campaign_id": "123456",
"campaign_name": "Summer Sale Campaign",
"advertiser_id": "1234567890",
"objective_type": "TRAFFIC",
"status": "CAMPAIGN_STATUS_ENABLE",
"budget": 1000.00,
"budget_mode": "BUDGET_MODE_DAY",
"create_time": "2025-09-01 10:00:00",
"modify_time": "2025-10-01 15:30:00"
}
],
"pagination": {
"current_page": 1,
"total_pages": 5,
"total_records": 45,
"per_page": 10,
"has_next": true,
"has_prev": false
}
}

Error Handling:

  • Returns 400 if account ID invalid
  • Returns 400 if no OAuth token found (KEYS_NOT_FOUND)
  • Passes TikTok API errors to Express error middleware

List Ad Groups

getAdGroups(req, res, next)

Purpose: Retrieve paginated list of ad groups for the configured advertiser account

Source: Controllers/analytics.js

External API Endpoint: GET https://business-api.tiktok.com/v1.3/adgroup/get

Request:

GET /v1/integrations/tiktok/adgroups?limit=20&page=1&campaign_id=123456
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescription
limitNumberResults per page (becomes page_size)
pageNumberPage number (1-based, default: 1)
campaign_idStringFilter by campaign ID
adgroup_idsStringComma-separated adgroup IDs

Business Logic: Same as campaigns, but calls getAdGroups() provider function

API Response Example:

{
"code": 0,
"message": "OK",
"data": {
"list": [
{
"adgroup_id": "7890123",
"adgroup_name": "Mobile Users 25-34",
"campaign_id": "123456",
"status": "ADGROUP_STATUS_ENABLE",
"budget": 500.00,
"bid_price": 1.50,
"optimization_goal": "CLICK",
"create_time": "2025-09-02 11:00:00"
}
],
"page_info": {
"total_number": 120,
"page": 1,
"page_size": 20
}
}
}

List Ads

getAds(req, res, next)

Purpose: Retrieve paginated list of individual ads for the configured advertiser account

Source: Controllers/analytics.js

External API Endpoint: GET https://business-api.tiktok.com/v1.3/ad/get

Request:

GET /v1/integrations/tiktok/ads?limit=50&page=1&adgroup_id=7890123
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescription
limitNumberResults per page (becomes page_size)
pageNumberPage number (1-based, default: 1)
adgroup_idStringFilter by ad group ID
ad_idsStringComma-separated ad IDs

Business Logic: Same as campaigns, but calls getAds() provider function

API Response Example:

{
"code": 0,
"message": "OK",
"data": {
"list": [
{
"ad_id": "456789",
"ad_name": "Video Ad - Product Launch",
"adgroup_id": "7890123",
"campaign_id": "123456",
"status": "AD_STATUS_ENABLE",
"create_time": "2025-09-03 09:00:00",
"modify_time": "2025-09-05 14:20:00",
"ad_text": "Check out our new product!",
"video_id": "v1234567890"
}
],
"page_info": {
"total_number": 350,
"page": 1,
"page_size": 50
}
}
}

📈 Integrated Analytics Reporting

Generate Analytics Report

reports(req, res, next)

Purpose: Generate comprehensive analytics reports with custom dimensions, metrics, and filtering at campaign, ad group, or ad level

Source: Controllers/analytics.js

External API Endpoint: GET https://business-api.tiktok.com/v1.3/report/integrated/get/

Request:

GET /v1/integrations/tiktok/reports?data_level=AUCTION_CAMPAIGN&start_date=2025-09-01&end_date=2025-10-10&metrics=["impressions","clicks","spend"]&dimensions=["campaign_id","stat_time_day"]&limit=100&page=1
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescription
data_levelStringReporting level: AUCTION_CAMPAIGN, AUCTION_ADGROUP, AUCTION_AD
start_dateStringStart date (YYYY-MM-DD format)
end_dateStringEnd date (YYYY-MM-DD format)
metricsJSON ArrayMetrics to retrieve (e.g., ["impressions","clicks"])
dimensionsJSON ArrayDimensions for grouping (e.g., ["campaign_id"])
limitNumberResults per page (becomes page_size)
pageNumberPage number (1-based, default: 1)
campaign_idsStringComma-separated campaign IDs to filter
adgroup_idsStringComma-separated adgroup IDs to filter
ad_idsStringComma-separated ad IDs to filter
campaign_statusStringFilter by campaign status
adgroup_statusStringFilter by adgroup status
ad_statusStringFilter by ad status
searchStringSearch term for name filtering
all_fieldsBooleanInclude all available metrics (see constants)

Returns: Promise<Object>

Business Logic Flow:

  1. Validate Account & Get Config

    • Check account access and fetch OAuth token
    • Extract advertiser_id from config
    • Return error if not found
  2. Handle all_fields Parameter

    • If all_fields=true, push all available metrics from constants
    • Metrics defined in constants/constants.js
  3. Status Filtering Logic (Complex Multi-Call Process)

    For each data level, perform preliminary API calls to filter by status:

    For AUCTION_CAMPAIGN level:

    • Call getCampaignsList() with:
      • fields: ["campaign_id", "secondary_status", "budget"]
      • filtering.secondary_status: If campaign_status provided
      • filtering.campaign_name: If search provided
      • filtering.campaign_ids: If campaign_ids provided
    • Extract all matching campaign_id values
    • Set filtered IDs in main query parameters
    • Return empty array if no campaigns match filters

    For AUCTION_ADGROUP level:

    • Call getAdGroups() with:
      • fields: ["adgroup_id", "secondary_status", "schedule_infos", "budget", "bid_price"]
      • filtering.secondary_status: If adgroup_status provided
      • filtering.adgroup_name: If search provided
      • filtering.adgroup_ids: If adgroup_ids provided
    • Extract all matching adgroup_id values
    • Set filtered IDs in main query parameters
    • Return empty array if no adgroups match filters

    For AUCTION_AD level:

    • Call getAds() with:
      • fields: ["ad_id", "secondary_status"]
      • filtering.secondary_status: If ad_status provided
      • filtering.ad_ids: If ad_ids provided
    • Note: Ad name search not supported by TikTok API
    • Extract all matching ad_id values
    • Set filtered IDs in main query parameters
    • Return empty array if no ads match filters
  4. Build Filtering Array

    • Convert ID filters to TikTok filtering format:
      filtering: [
      {
      field_name: 'campaign_ids',
      filter_type: 'IN',
      filter_value: '[123,456,789]',
      },
      ];
    • Stringify filtering array for API
  5. Call Integrated Report API

    • Provider Function: tiktokAnalyticsProvider.getCreativereports()
    • HTTP Method: GET
    • URL: {TIKTOK_BASE_URL}/{TIKTOK_VERSION}/report/integrated/get/
    • Headers: Access-Token: {access_token}, Content-Type: application/json
    • Query Params:
      • advertiser_id
      • data_level
      • start_date, end_date
      • metrics (JSON stringified)
      • dimensions (JSON stringified)
      • filtering (JSON stringified)
      • page_size (from limit)
      • page
  6. Merge Status Data into Report

    • For each row in report data.list:
    • Match by campaign_id, adgroup_id, or ad_id
    • Add extra fields from status API calls:
      • secondary_status - Current status
      • budget - Budget amount
      • schedule_infos - Schedule details (adgroups)
      • bid_price - Bid price (adgroups)
  7. Generate Pagination

    • Extract page_info.total_number from report response
    • Call utilities.generatePagination(limit, page, total_number)
  8. Return Combined Response

    • Report data with merged status fields
    • Pagination metadata

API Request Example:

GET https://business-api.tiktok.com/v1.3/report/integrated/get/?advertiser_id=1234567890&data_level=AUCTION_CAMPAIGN&start_date=2025-09-01&end_date=2025-10-10&metrics=["impressions","clicks","spend","ctr","cpc"]&dimensions=["campaign_id","stat_time_day"]&page_size=100&page=1&filtering=[{"field_name":"campaign_ids","filter_type":"IN","filter_value":"[123456,789012]"}]
Headers:
Access-Token: act.1234567890abcdef...
Content-Type: application/json

API Response Example:

{
"code": 0,
"message": "OK",
"data": {
"list": [
{
"dimensions": {
"campaign_id": "123456",
"stat_time_day": "2025-09-01"
},
"metrics": {
"impressions": 45000,
"clicks": 1200,
"spend": 450.75,
"ctr": 2.67,
"cpc": 0.38,
// Merged from status API:
"secondary_status": "CAMPAIGN_STATUS_ENABLE",
"budget": 1000.00
}
},
{
"dimensions": {
"campaign_id": "123456",
"stat_time_day": "2025-09-02"
},
"metrics": {
"impressions": 52000,
"clicks": 1450,
"spend": 520.30,
"ctr": 2.79,
"cpc": 0.36,
"secondary_status": "CAMPAIGN_STATUS_ENABLE",
"budget": 1000.00
}
}
],
"page_info": {
"total_number": 300,
"page": 1,
"page_size": 100
}
}
}

Success Response:

{
"success": true,
"message": "SUCCESS",
"data": [
{
"dimensions": {
"campaign_id": "123456",
"stat_time_day": "2025-09-01"
},
"metrics": {
"impressions": 45000,
"clicks": 1200,
"spend": 450.75,
"ctr": 2.67,
"cpc": 0.38,
"secondary_status": "CAMPAIGN_STATUS_ENABLE",
"budget": 1000.00
}
}
],
"pagination": {
"current_page": 1,
"total_pages": 3,
"total_records": 300,
"per_page": 100,
"has_next": true,
"has_prev": false
}
}

Error Handling:

  • Returns empty array if no matching campaigns/adgroups/ads found
  • Logs errors during status filtering (non-fatal)
  • Passes TikTok API errors to Express error middleware

Side Effects:

  • ⚠️ Makes multiple API calls for status filtering
  • ⚠️ Can consume significant API quota for large reports
  • ⚠️ Merges data from multiple API responses

🎯 Available Metrics & Dimensions

Popular Metrics:

MetricDescription
impressionsNumber of times ads were shown
clicksNumber of ad clicks
spendTotal ad spend in account currency
ctrClick-through rate (clicks/impressions)
cpcCost per click (spend/clicks)
conversionTotal conversions
cost_per_conversionAverage cost per conversion
video_play_actionsVideo play count
video_watched_2sVideos watched for 2+ seconds
video_watched_6sVideos watched for 6+ seconds
reachUnique users reached
frequencyAverage impressions per user

Popular Dimensions:

DimensionDescription
campaign_idCampaign identifier
campaign_nameCampaign name
adgroup_idAd group identifier
adgroup_nameAd group name
ad_idIndividual ad identifier
ad_nameAd name
stat_time_dayDate (YYYY-MM-DD format)
stat_time_hourHour breakdown

All Available Fields: See constants/constants.js allFields array for complete list


🔀 Data Levels

TikTok supports three reporting levels:

AUCTION_CAMPAIGN

  • Use Case: Campaign performance overview
  • Dimensions Available: Campaign ID, name, date/time
  • Best For: High-level budget and performance tracking

AUCTION_ADGROUP

  • Use Case: Ad group performance and targeting analysis
  • Dimensions Available: Campaign + ad group info, targeting details
  • Best For: Audience and placement performance

AUCTION_AD

  • Use Case: Individual ad creative performance
  • Dimensions Available: Campaign + adgroup + ad info
  • Best For: Creative optimization and A/B testing

⚠️ Important Notes

  • 🔐 Advertiser Required: All operations require saved advertiser config
  • 📊 Multiple API Calls: Reporting with status filters makes 2-3 API calls
  • 🎯 Status Filtering: Separate API calls needed for status-based filtering
  • 📅 Date Range: Reports support custom date ranges
  • 💰 Currency: All spend values in advertiser account currency
  • ⏱️ Timezone: All timestamps in advertiser account timezone
  • 📈 Pagination: Large reports automatically paginated
  • 🔄 Status Merging: Report data merged with real-time status info
  • Rate Limits: High-volume reports may hit rate limits
  • 🚫 Search Limitations: Ad name search not supported by TikTok API

💬

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