Systems Library / Marketing Automation / How to Set Up TikTok Ads API Reporting
Marketing Automation paid advertising

How to Set Up TikTok Ads API Reporting

Pull TikTok ad performance data automatically for cross-platform analysis.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

TikTok ads API reporting automation pulls your ad data into the same pipeline as Meta and Google. Instead of logging into three platforms every morning, you pull everything into one database. I set this up for any client running TikTok alongside other channels.

TikTok's API is newer than Meta's but follows similar patterns. The authentication is different, but the data structure is straightforward once you get past the initial setup.

What You Need Before Starting

Step 1: Get Your API Credentials

Go to TikTok Marketing API portal. Create an app. Get approved (usually takes 1-2 business days). Once approved, generate a long-lived access token.

Store it in your .env:

TIKTOK_ACCESS_TOKEN=your_token_here
TIKTOK_ADVERTISER_ID=your_advertiser_id

Step 2: Build the Data Fetcher

import requests
import os
from datetime import datetime, timedelta
from dotenv import load_dotenv

load_dotenv()

TIKTOK_BASE = "https://business-api.tiktok.com/open_api/v1.3"

def fetch_tiktok_ads(date=None):
    if not date:
        date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
    
    token = os.getenv("TIKTOK_ACCESS_TOKEN")
    advertiser_id = os.getenv("TIKTOK_ADVERTISER_ID")
    
    headers = {"Access-Token": token}
    
    params = {
        "advertiser_id": advertiser_id,
        "report_type": "BASIC",
        "data_level": "AUCTION_AD",
        "dimensions": '["ad_id", "stat_time_day"]',
        "metrics": '["spend", "impressions", "clicks", "cpc", "ctr", "conversion", "cost_per_conversion", "reach"]',
        "start_date": date,
        "end_date": date,
        "page_size": 100,
    }
    
    resp = requests.get(f"{TIKTOK_BASE}/report/integrated/get/", headers=headers, params=params)
    data = resp.json()
    
    if data.get("code") != 0:
        print(f"TikTok API error: {data.get('message')}")
        return []
    
    rows = []
    for item in data.get("data", {}).get("list", []):
        metrics = item.get("metrics", {})
        dimensions = item.get("dimensions", {})
        
        rows.append({
            "date": date,
            "ad_id": dimensions.get("ad_id", ""),
            "spend": float(metrics.get("spend", 0)),
            "impressions": int(metrics.get("impressions", 0)),
            "clicks": int(metrics.get("clicks", 0)),
            "cpc": float(metrics.get("cpc", 0)),
            "ctr": float(metrics.get("ctr", 0)),
            "conversions": int(metrics.get("conversion", 0)),
            "cpa": float(metrics.get("cost_per_conversion", 0)),
            "reach": int(metrics.get("reach", 0)),
        })
    
    return rows

Step 3: Get Campaign and Ad Names

TikTok's reporting endpoint returns IDs, not names. You need a separate call:

def get_ad_details(ad_ids):
    token = os.getenv("TIKTOK_ACCESS_TOKEN")
    advertiser_id = os.getenv("TIKTOK_ADVERTISER_ID")
    
    headers = {"Access-Token": token}
    params = {
        "advertiser_id": advertiser_id,
        "filtering": f'{{"ad_ids": {ad_ids}}}',
        "fields": '["ad_id", "ad_name", "campaign_name", "adgroup_name"]',
    }
    
    resp = requests.get(f"{TIKTOK_BASE}/ad/get/", headers=headers, params=params)
    data = resp.json()
    
    details = {}
    for ad in data.get("data", {}).get("list", []):
        details[ad["ad_id"]] = {
            "ad_name": ad.get("ad_name", ""),
            "campaign_name": ad.get("campaign_name", ""),
            "adgroup_name": ad.get("adgroup_name", ""),
        }
    return details

Step 4: Store in Your Unified Database

import sqlite3

def store_tiktok_data(db_path, rows, ad_details):
    conn = sqlite3.connect(db_path)
    conn.execute("""CREATE TABLE IF NOT EXISTS tiktok_daily (
        id INTEGER PRIMARY KEY, date TEXT, ad_id TEXT, ad_name TEXT,
        campaign_name TEXT, adgroup_name TEXT, spend REAL, impressions INTEGER,
        clicks INTEGER, cpc REAL, ctr REAL, conversions INTEGER, cpa REAL,
        reach INTEGER, fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )""")
    
    for row in rows:
        details = ad_details.get(row["ad_id"], {})
        conn.execute("""INSERT INTO tiktok_daily 
            (date, ad_id, ad_name, campaign_name, adgroup_name, spend, impressions,
             clicks, cpc, ctr, conversions, cpa, reach)
            VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)""",
            (row["date"], row["ad_id"], details.get("ad_name", ""),
             details.get("campaign_name", ""), details.get("adgroup_name", ""),
             row["spend"], row["impressions"], row["clicks"], row["cpc"],
             row["ctr"], row["conversions"], row["cpa"], row["reach"]))
    
    conn.commit()
    conn.close()

Step 5: Run It Daily

if __name__ == "__main__":
    rows = fetch_tiktok_ads()
    if rows:
        ad_ids = [r["ad_id"] for r in rows]
        details = get_ad_details(ad_ids)
        store_tiktok_data("ads_unified.db", rows, details)
        print(f"Stored {len(rows)} TikTok ad rows")
    else:
        print("No TikTok data to pull")
0 7 * * * cd /path/to/project && python3 tiktok_pull.py >> /var/log/tiktok.log 2>&1

Now your TikTok data lives alongside Meta and Google in the same database. Same queries, same dashboards, same alerts.

What to Build Next

Add TikTok data to your cross-platform dashboard. Then build a comparison report that shows which platform delivers the best CPA for each audience segment.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems