DynamicAds Cookbook
DynamicAds Cookbook
Frontend SDK Usage
Learn how to use the DynamicAds web components in your frontend.
Basic Usage
<!-- Add the SDK script -->
<script src="https://dynamicads.app/sdk.js"></script>
<!-- Use components -->
<dynamic-ad ad-id="your-ad-id"></dynamic-ad>
<dynamic-agent agent-id="your-agent-id"></dynamic-agent>
<!-- Basic styling -->
<style>
/* Ad container styles */
.dynamic-ad-container {
width: 100%;
max-width: 320px;
margin: 0 auto;
border-radius: 0.75rem;
overflow: hidden;
background: rgb(17 24 39);
height: auto;
display: flex;
flex-direction: column;
position: relative;
}
/* Agent container styles */
.dynamic-agent-container {
width: 320px;
max-width: 320px;
margin: 0 auto;
position: relative;
}
.agent-ad {
width: 100%;
position: relative;
}
.agent-preview {
position: absolute;
bottom: 15px;
right: -290px;
width: 250px;
min-height: 150px;
border-radius: 0.75rem;
overflow: visible;
background: transparent;
z-index: 100;
transform: scale(0.85);
transform-origin: bottom right;
}
/* Mobile responsive styles */
@media (max-width: 640px) {
.agent-preview {
position: relative;
bottom: 0;
right: 0;
width: 100%;
transform: none;
margin-top: 1rem;
}
}
</style>
Basic setup with components and styling. The SDK automatically handles all required dependencies.
React Integration
import { useEffect, useRef } from 'react';
function DynamicAdsComponent() {
// Keep track of the SDK script
const sdkScriptRef = useRef<HTMLScriptElement | null>(null);
useEffect(() => {
// Clean up previous script if it exists
if (sdkScriptRef.current) {
sdkScriptRef.current.remove();
}
// Add SDK script
const script = document.createElement('script');
script.src = 'https://dynamicads.app/sdk.js';
script.async = true;
script.type = 'text/javascript';
sdkScriptRef.current = script;
document.body.appendChild(script);
// Clean up on unmount
return () => {
if (sdkScriptRef.current) {
sdkScriptRef.current.remove();
}
};
}, []); // Empty deps array means this runs once on mount
return (
<div>
{/* Ad Component */}
<div className="dynamic-ad-container">
<dynamic-ad ad-id="your-ad-id"></dynamic-ad>
</div>
{/* Agent Component */}
<div className="dynamic-agent-container">
<div className="agent-ad">
<dynamic-agent agent-id="your-agent-id"></dynamic-agent>
</div>
</div>
</div>
);
}
Integration with React components. The useRef hook helps manage the SDK script lifecycle, preventing memory leaks and duplicate script loading.
Advanced Configuration
// Initialize with options
DynamicAds.init({
debug: true, // Enable debug logging
baseUrl: 'https://custom-api.example.com' // Custom API endpoint
});
// Use with custom styling
<div class="custom-container">
<dynamic-ad
ad-id="your-ad-id"
style="max-width: 500px; margin: 0 auto;"
></dynamic-ad>
</div>
<style>
.custom-container dynamic-ad {
/* Custom styles */
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
Advanced configuration and styling options
Prompting Techniques
Learn how to craft effective prompts for generating compelling ads.
Structure and Detail
Create a luxury resort ad with drone shots of overwater villas, crystal clear waters, and palm trees. Begin with aerial view, transition to sunset. Text overlay: "Paradise Found". Show price: "$12,000/night" on hover.
Specifies visual flow, timing, and UI interactions
Brand Voice
Design a tech startup ad that feels innovative and dynamic. Show code transforming into 3D product visualizations. Use modern, minimalist aesthetic with bold typography. Voice should be confident but approachable.
Defines style, tone, and brand personality
Python Integration Examples
Basic Integration with Caching
from dynamicads import DynamicAdsClient
import asyncio
from typing import List, Dict
import json
from pathlib import Path
import aiohttp
import pandas as pd
class AdGenerator:
def __init__(self, api_key: str):
self.client = DynamicAdsClient(api_key)
self.cache_dir = Path("ad_cache")
self.cache_dir.mkdir(exist_ok=True)
async def generate_batch(
self,
prompts: List[Dict[str, any]],
max_concurrent: int = 5
):
"""Generate multiple ads concurrently with rate limiting."""
semaphore = asyncio.Semaphore(max_concurrent)
async with aiohttp.ClientSession() as session:
tasks = []
for prompt in prompts:
task = asyncio.create_task(
self._generate_single(session, semaphore, prompt)
)
tasks.append(task)
return await asyncio.gather(*tasks)
async def _generate_single(
self,
session: aiohttp.ClientSession,
semaphore: asyncio.Semaphore,
prompt: Dict[str, any]
):
"""Generate a single ad with caching and error handling."""
cache_key = self._get_cache_key(prompt)
cache_file = self.cache_dir / f"{cache_key}.json"
# Check cache first
if cache_file.exists():
return json.loads(cache_file.read_text())
async with semaphore:
try:
# Start generation
ad = await self.client.generate(
prompt=prompt["text"],
media_type=prompt.get("type", "video"),
dimensions=prompt.get("dimensions", {
"width": 672,
"height": 384
})
)
# Wait for completion
completed = await self.client.wait_for_completion(
ad.id,
timeout=300
)
# Cache result
result = {
"id": completed.id,
"status": "complete",
"media_url": completed.media_url,
"voice_url": completed.voice_url,
"prompt": prompt
}
cache_file.write_text(json.dumps(result))
return result
except Exception as e:
return {
"status": "error",
"error": str(e),
"prompt": prompt
}
def _get_cache_key(self, prompt: Dict[str, any]) -> str:
"""Generate a unique cache key for a prompt."""
prompt_str = json.dumps(prompt, sort_keys=True)
return hashlib.md5(prompt_str.encode()).hexdigest()
# Example usage
async def main():
generator = AdGenerator("your-api-key")
# Load prompts from CSV
df = pd.read_csv("prompts.csv")
prompts = df.to_dict("records")
# Generate ads in parallel
results = await generator.generate_batch(prompts)
# Save results
output_df = pd.DataFrame(results)
output_df.to_csv("results.csv", index=False)
if __name__ == "__main__":
asyncio.run(main())
Advanced Integration
# Advanced caching with Redis
from redis import Redis
from typing import Optional
import pickle
class RedisCache:
def __init__(self, redis_url: str):
self.redis = Redis.from_url(redis_url)
self.ttl = 60 * 60 * 24 # 24 hours
async def get(self, key: str) -> Optional[dict]:
value = self.redis.get(key)
return pickle.loads(value) if value else None
async def set(self, key: str, value: dict):
self.redis.setex(
key,
self.ttl,
pickle.dumps(value)
)
# Advanced error handling and retry logic
from tenacity import (
retry,
stop_after_attempt,
wait_exponential
)
class RobustAdGenerator:
def __init__(
self,
api_key: str,
cache: Optional[RedisCache] = None
):
self.client = DynamicAdsClient(api_key)
self.cache = cache
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10)
)
async def generate_with_retry(self, prompt: Dict[str, any]):
"""Generate ad with automatic retries on failure."""
try:
if self.cache:
cached = await self.cache.get(
self._get_cache_key(prompt)
)
if cached:
return cached
ad = await self.client.generate(
prompt=prompt["text"],
media_type=prompt.get("type", "video")
)
# Monitor generation progress
async for status in self._monitor_progress(ad.id):
if status.get("error"):
raise Exception(status["error"])
if status["status"] == "complete":
if self.cache:
await self.cache.set(
self._get_cache_key(prompt),
status
)
return status
except Exception as e:
logger.error(f"Generation failed: {e}")
raise
async def _monitor_progress(self, ad_id: str):
"""Monitor ad generation progress with timeouts."""
start_time = time.time()
while True:
if time.time() - start_time > 300:
raise TimeoutError("Generation timed out")
status = await self.client.get_ad(ad_id)
yield status
if status["status"] in ["complete", "error"]:
break
await asyncio.sleep(2)
React Integration Examples
Basic Integration
import { useEffect, useState } from 'react';
import { DynamicAdsClient } from '@dynamicads/sdk';
function AdGallery() {
const [ads, setAds] = useState([]);
const [loading, setLoading] = useState(true);
const client = new DynamicAdsClient('your-api-key');
useEffect(() => {
async function loadAds() {
const response = await client.listAds();
setAds(response.ads);
setLoading(false);
}
loadAds();
}, []);
return (
<div className="grid grid-cols-3 gap-4">
{ads.map(ad => (
<div key={ad.id}>
<dynamic-ad ad-id={ad.id}></dynamic-ad>
</div>
))}
</div>
);
}
Advanced Integration
// Advanced React component with web components
import { useInfiniteQuery } from '@tanstack/react-query';
import { useInView } from 'react-intersection-observer';
import { DynamicAdsClient } from '@dynamicads/sdk';
const client = new DynamicAdsClient('your-api-key');
// Custom hook for SDK initialization
function useDynamicAds() {
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://dynamicads.app/sdk.js';
script.async = true;
script.onload = () => {
window.DynamicAds.init({
debug: process.env.NODE_ENV === 'development'
});
};
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
};
}, []);
}
// Advanced ad gallery with infinite scroll
function AdGallery() {
useDynamicAds();
const { ref, inView } = useInView();
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage
} = useInfiniteQuery({
queryKey: ['ads'],
queryFn: ({ pageParam = 1 }) =>
client.listAds({ page: pageParam }),
getNextPageParam: (lastPage) =>
lastPage.hasMore ? lastPage.page + 1 : undefined,
});
useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView, hasNextPage]);
return (
<div className="space-y-4">
{data?.pages.map((page) =>
page.ads.map((ad) => (
<div key={ad.id} className="ad-container">
<dynamic-ad ad-id={ad.id}></dynamic-ad>
{ad.hasAgent && (
<dynamic-agent agent-id={ad.agentId}></dynamic-agent>
)}
</div>
))
)}
<div ref={ref}>
{isFetchingNextPage && <LoadingSpinner />}
</div>
</div>
);
}
// Advanced ad card with preloading
function AdCard({ ad }) {
const [loaded, setLoaded] = useState(false);
const { ref, inView } = useInView({
triggerOnce: true,
rootMargin: '50px 0px',
});
useEffect(() => {
if (inView && ad.mediaUrl) {
const media = new Image();
media.src = ad.mediaUrl;
media.onload = () => setLoaded(true);
}
}, [inView, ad.mediaUrl]);
return (
<div
ref={ref}
className={cn(
'transition-opacity duration-500',
loaded ? 'opacity-100' : 'opacity-0'
)}
>
<dynamic-ad ad-id={ad.id}></dynamic-ad>
</div>
);
}
Batch Processing Examples
Learn how to efficiently process multiple ads in parallel.
// TypeScript batch processor
import {
DynamicAdsClient,
type Ad,
type GenerateOptions
} from '@dynamicads/sdk';
import pLimit from 'p-limit';
import { chunk } from 'lodash';
interface BatchOptions {
concurrency?: number;
chunkSize?: number;
onProgress?: (progress: number) => void;
}
class BatchProcessor {
private client: DynamicAdsClient;
private limit: ReturnType<typeof pLimit>;
constructor(
apiKey: string,
private options: BatchOptions = {}
) {
this.client = new DynamicAdsClient(apiKey);
this.limit = pLimit(options.concurrency || 5);
}
async processBatch(
prompts: GenerateOptions[]
): Promise<Array<Ad | Error>> {
const chunks = chunk(
prompts,
this.options.chunkSize || 10
);
let completed = 0;
const results: Array<Ad | Error> = [];
for (const chunk of chunks) {
const chunkResults = await Promise.all(
chunk.map(prompt =>
this.limit(async () => {
try {
const ad = await this.client.generate(prompt);
const complete = await this.client
.waitForCompletion(ad.id);
completed++;
this.options.onProgress?.(
(completed / prompts.length) * 100
);
return complete;
} catch (error) {
return error as Error;
}
})
)
);
results.push(...chunkResults);
}
return results;
}
}
// Usage example
const processor = new BatchProcessor('your-api-key', {
concurrency: 5,
chunkSize: 10,
onProgress: (progress) => {
console.log(`Progress: ${progress.toFixed(1)}%`);
}
});
const prompts = [
{
prompt: 'Luxury resort ad...',
mediaType: 'video'
},
// ... more prompts
];
const results = await processor.processBatch(prompts);