The Meta Graph API offers a programmatic gateway to a wealth of data and functionality within the Meta ecosystem. A standout feature is the Ads Library (formerly known as ads_archive), providing unprecedented transparency into advertising across Facebook, Instagram, and other platforms. For developers looking to harness this data, a robust and efficient API is crucial. This blog post explores how to build such an API using FastAPI, a modern, high-performance Python web framework. We'll delve into practical code examples, covering everything from setting up the API to handling authentication, querying the Ads Library, and managing potential errors.
Why FastAPI for Meta Ads Library Integration?
FastAPI is an excellent choice for building an API to access the Meta Ads Library due to its numerous advantages:
- Speed and Performance: Built on top of Starlette and Pydantic, FastAPI offers impressive performance, crucial for handling large volumes of ad data.
- Automatic Data Validation: Pydantic's data validation ensures that your API receives and processes data in the expected format, reducing errors.
- Type Hints: Type hints enhance code readability and maintainability, making it easier to understand and debug.
- Dependency Injection: FastAPI's dependency injection system simplifies code organization and testing.
- Automatic API Documentation: FastAPI automatically generates interactive API documentation (using Swagger UI or ReDoc), making it easy for developers to understand and use your API.
Setting Up Your FastAPI Project
Before diving into the code, set up your FastAPI project:
Install Dependencies:
pip install fastapi uvicorn python-dotenv httpx
pip install "uvicorn[standard]"
Project Structure:
A well-organized project structure is essential for maintainability:
/your_project
├── app/
│ ├── __init__.py
│ ├── api/
│ │ ├── meta.py # Meta Ads Library API endpoints
│ ├── schemas.py # Pydantic models for data validation
│ ├── utils.py # Utility functions for interacting with Meta API
│ ├── main.py # Main FastAPI application
├── .env # Environment variables (e.g., access token)
├── requirements.txt # Project dependencies
├── Dockerfile # Dockerfile for containerization
Code Examples: Building the API
Let's break down the code needed to create a FastAPI-based API for the Meta Ads Library.
.env File (Environment Variables):
Create a .env file to store sensitive information, such as your Meta Access Token.
META_ACCESS_TOKEN="YOUR_META_ACCESS_TOKEN"
app/schemas.py (Pydantic Models):
Define Pydantic models to validate the structure of incoming requests and outgoing responses.
from typing import Optional, List
from pydantic import BaseModel
from datetime import datetime
class MetaAdsRequest(BaseModel):
limit: Optional[int] = 10
after: Optional[str] = None
ad_delivery_date_min: Optional[str] = None
ad_delivery_date_max: Optional[str] = None
search_terms: Optional[str] = None
ad_reached_countries: str # Required
media_type: Optional[str] = None
ad_active_status: Optional[str] = None
search_type: Optional[str] = None
ad_type: Optional[str] = None
languages: Optional[str] = None
publisher_platforms: Optional[str] = None
search_page_ids: Optional[str] = None
unmask_removed_content: Optional[str] = None
class AdData(BaseModel): # represents individual ad
ad_creative_link_captions: Optional[List[str]] = None
ad_creative_link_descriptions: Optional[List[str]] = None
ad_snapshot_url: str
page_id: str
page_name: str
publisher_platforms: List[str]
ad_delivery_date: str
class MetaAdsResponse(BaseModel):
data: List[AdData]
paging: Optional[dict] # Optional paging information
app/utils.py (Utility Functions):
Create utility functions to encapsulate the logic for interacting with the Meta Ads Library API.
import httpx
from typing import Optional
from fastapi import HTTPException
from urllib.parse import urlencode
import os
from dotenv import load_dotenv
load_dotenv()
META_ACCESS_TOKEN = os.getenv("META_ACCESS_TOKEN")
async def get_meta_ads(
limit: int = 10,
after: str | None = None,
ad_delivery_date_min: str | None = None,
ad_delivery_date_max: str | None = None,
search_terms: str | None = None,
ad_reached_countries: str | None = None,
media_type: str | None = None,
ad_active_status: str | None = None,
search_type: str | None = None,
ad_type: str | None = None,
languages: str | None = None,
publisher_platforms: str | None = None,
search_page_ids: str | None = None,
unmask_removed_content: str | None = None,
):
"""Fetches ads data from Meta Ad Library API."""
base_url = "https://graph.facebook.com/v21.0/ads_archive?fields=ad_creative_link_captions,ad_creative_link_descriptions,ad_snapshot_url,page_id,page_name,publisher_platforms,ad_delivery_date"
params = {
"access_token": META_ACCESS_TOKEN,
"limit": limit,
"ad_reached_countries": ad_reached_countries,
}
if after:
params["after"] = after
if ad_delivery_date_min:
params["ad_delivery_date_min"] = ad_delivery_date_min
if ad_delivery_date_max:
params["ad_delivery_date_max"] = ad_delivery_date_max
if search_terms:
params["search_terms"] = search_terms
if media_type:
params["media_type"] = media_type
if ad_active_status:
params["ad_active_status"] = ad_active_status
if search_type:
params["search_type"] = search_type
if ad_type:
params["ad_type"] = ad_type
if languages:
params["languages"] = languages
if publisher_platforms:
params["publisher_platforms"] = publisher_platforms
if search_page_ids:
params["search_page_ids"] = search_page_ids
if unmask_removed_content:
params["unmask_removed_content"] = unmask_removed_content
url = f"{base_url}&{urlencode(params)}"
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
return response.json() # Return the JSON response
except httpx.HTTPError as e:
raise HTTPException(status_code=e.response.status_code, detail=str(e))
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Failed to fetch Meta ads data: {e}"
)
app/api/meta.py (API Endpoints):
Create the API endpoints using FastAPI's router.
from typing import Optional
from fastapi import FastAPI, HTTPException, Depends, APIRouter
from app.schemas import MetaAdsRequest, MetaAdsResponse
from app.utils import get_meta_ads
router = APIRouter()
@router.post("/meta-ads", response_model=MetaAdsResponse)
async def fetch_meta_ads_endpoint(request: MetaAdsRequest):
"""
Fetches ads data from the Meta Ad Library API.
Requires at least 'ad_reached_countries' to be provided.
"""
try:
if not request.ad_reached_countries:
raise HTTPException(
status_code=400,
detail="ad_reached_countries is a required parameter.",
)
# Call the utility function to fetch ads
ads_data = await get_meta_ads(
limit=request.limit,
after=request.after,
ad_delivery_date_min=request.ad_delivery_date_min,
ad_delivery_date_max=request.ad_delivery_date_max,
search_terms=request.search_terms,
ad_reached_countries=request.ad_reached_countries,
media_type=request.media_type,
ad_active_status=request.ad_active_status,
search_type=request.search_type,
ad_type=request.ad_type,
languages=request.languages,
publisher_platforms=request.publisher_platforms,
search_page_ids=request.search_page_ids,
unmask_removed_content=request.unmask_removed_content,
)
return ads_data
except HTTPException as http_ex:
# Re-raise HTTPExceptions to preserve status codes
raise http_ex
except Exception as e:
# Handle other exceptions
raise HTTPException(
status_code=500, detail=f"An unexpected error occurred: {e}"
)
app/main.py (FastAPI Application):
Create the main FastAPI application instance and include the router.
from fastapi import FastAPI
from app.api import meta
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# CORS (Cross-Origin Resource Sharing) settings
origins = [
"http://localhost:3000", # Example origin for your frontend
"https://your-frontend-domain.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(meta.router, prefix="/api", tags=["Meta Ads"])
Running the Application
To run your FastAPI application:
fastapi dev
Best Practices
- Environment Variables: Store sensitive information like access tokens in environment variables instead of hardcoding them into your code.
- Error Handling: Implement robust error handling to catch potential exceptions and provide informative error messages to clients.
- Data Validation: Use Pydantic models to validate the structure and content of incoming requests and outgoing responses.
- Asynchronous Operations: Use async and await for I/O-bound operations (like API requests) to avoid blocking the event loop and improve performance.
- Pagination: Implement pagination to handle large datasets efficiently. The Meta Ads Library API provides pagination through the after parameter.
- Rate Limiting: Be aware of rate limits imposed by the Meta Graph API. Implement rate limiting in your API to avoid exceeding these limits.
Conclusion
This blog post has demonstrated how to build a robust and efficient API for accessing the Meta Ads Library using FastAPI. By leveraging FastAPI's features, you can create a well-structured, performant, and maintainable API to unlock the wealth of data available within the Meta ecosystem. Remember to always adhere to Meta's API terms of service and prioritize user privacy when working with advertising data.
Comments
Post a Comment
Oof!