20 KiB
name, description
| name | description |
|---|---|
| seo-multi-channel | Generate multi-channel marketing content (Facebook, Ads, Blog, X) with Thai language support, image generation, and website-creator integration. Use when user wants to create content for multiple channels from a single topic. |
🎯 SEO Multi-Channel Content Generator
Skill Name: seo-multi-channel
Category: deep
Load Skills: ['image-generation', 'image-edit', 'website-creator']
🚀 Purpose
Generate marketing content for multiple channels from a single topic with:
- ✅ Priority Channels: Facebook > Facebook Ads > Google Ads > Blog > X (Twitter)
- ✅ Thai Language Support: Full Thai text processing with PyThaiNLP
- ✅ Image Generation: Auto-generate images for social/ads, save to website repo for blog
- ✅ Product Image Handling: Browse website repo first, then ask user or enhance with image-edit
- ✅ Website-Creator Integration: Auto-publish blog posts to Astro content collections
- ✅ API-Ready Output: Structured JSON for future ad platform API integration
- ✅ Per-Project Context: Context files in each website repo
Use Cases:
- Multi-Channel Campaign: One topic → Facebook post + Facebook Ads + Google Ads + Blog + X thread
- Social-Only: Facebook post + Facebook Ads for product promotion
- Blog-First: SEO blog post with auto-publish to website
- Ads-Only: Google Ads + Facebook Ads copy for existing product
📋 Pre-Flight Questions
MUST ask before generating:
-
Topic/Subject: What topic do you want content about?
-
Channels Needed: (Default: All channels)
- Facebook (organic posts)
- Facebook Ads (paid campaigns)
- Google Ads (search campaigns)
- Blog (SEO articles)
- X/Twitter (threads)
-
Content Type: (Auto-detect or ask)
- Product/Service (requires product images)
- Knowledge/Educational (generates fresh images)
- Statistics/Data (generates infographic-style images)
- Announcement/News (may not need images)
-
Target Language: (Auto-detect from topic or ask)
- Thai (default for Thai topics)
- English
- Bilingual (both Thai + English)
-
For Product Content:
- Product name
- Website repo path (to browse for existing images)
- Product URL (if available)
-
For Blog Posts:
- Target keyword for SEO
- Should I auto-publish to website? (yes/no)
- Website repo path (if auto-publish)
-
Tone/Formality: (Auto-detect from context or default)
- กันเอง (Casual) - for social media
- ปกติ (Normal) - for blog
- เป็นทางการ (Formal) - for corporate
🔄 Workflow
Phase 1: Context Loading
-
Load Project Context:
- Read
context/brand-voice.mdfrom website repo - Read
context/target-keywords.md - Read
context/seo-guidelines.md - Auto-detect formality level from brand voice
- Read
-
Check Data Services:
- Check if GA4 configured (skip if not)
- Check if GSC configured (skip if not)
- Check if DataForSEO configured (skip if not)
- Check if Umami configured (skip if not)
- Fetch available performance data
-
Load Channel Templates:
- Load YAML templates for selected channels
- Apply brand voice customizations
Phase 2: Content Generation
For Each Channel:
Facebook (Organic):
Output:
- primary_text: 125-250 chars (Thai can be longer)
- headline: 100 chars max
- hashtags: 3-5 recommended
- cta: เลือกจาก ["เรียนรู้เพิ่มเติม", "สมัครเลย", "ซื้อเลย", "ดูรายละเอียด"]
- image: Generated or edited
- variations: 5 options
Facebook Ads:
Output:
- primary_text: 125 chars recommended (5000 max)
- headline: 40 chars
- description: 90 chars
- cta: Button choice
- image: Product-focused or benefit-focused
- variations: 5 options
- api_ready: true (matches Meta Ads API structure)
Google Ads:
Output:
- headlines: 15 variations (30 chars each)
- descriptions: 4 variations (90 chars each)
- keywords: Suggested keyword list
- negative_keywords: Suggested negatives
- ad_extensions: Sitelink, callout, structured snippets
- api_ready: true (matches Google Ads API structure)
Blog (SEO Article):
Output:
- markdown: Full article with frontmatter
- word_count: 1500-3000 (Thai), 2000-3000 (English)
- keyword_density: 1.0-1.5% (Thai), 1.5-2% (English)
- meta_title: 50-60 chars
- meta_description: 150-160 chars
- slug: Auto-generated (Thai-friendly)
- images: Saved to website repo
- astro_ready: true (content collections format)
X/Twitter Thread:
Output:
- tweets: 5-10 tweet thread
- hook_tweet: First tweet (280 chars)
- body_tweets: 2-8 tweets (280 chars each)
- cta_tweet: Final tweet with CTA
- hashtags: 2-3 per tweet
- thread_title: Optional title card
Phase 3: Image Handling
Product Content:
1. Browse website repo for existing product images:
- Search: public/images/, src/assets/, **/*{product_name}*.{jpg,png,webp}
2. If images found:
- Select best image (highest quality, product-focused)
- Call image-edit skill:
prompt: "Enhance product image for {channel}, professional lighting, clean background, {channel}-specific dimensions"
3. If no images found:
- Ask user: "No product images found in repo. Please provide image path or URL."
- Wait for user to provide
- Then call image-edit
Non-Product Content:
1. Determine content type:
- Service → Professional illustration
- Knowledge → Educational visual metaphor
- Stats → Infographic with charts
- News → Clean, modern announcement style
2. Call image-generation skill:
prompt: "{content_type} illustration for {topic}, {style}, Thai-friendly aesthetic, {channel}-optimized dimensions"
3. Save images:
- Social/Ads → seo-multi-channel/generated-images/{topic}/{channel}/
- Blog → {website-repo}/public/images/blog/{slug}/
Phase 4: Output & Publishing
Output Structure:
output/{topic-slug}/
├── facebook/
│ ├── posts.json
│ └── images/
├── facebook_ads/
│ ├── ads.json
│ └── images/
├── google_ads/
│ └── ads.json
├── blog/
│ ├── article.md
│ └── images/
├── x/
│ └── thread.json
└── summary.json
Auto-Publish Blog (if enabled):
1. Parse frontmatter from blog markdown
2. Detect language (Thai → 'th', English → 'en')
3. Generate slug (Thai-friendly: use transliteration or keep Thai)
4. Save to: {website-repo}/src/content/blog/({lang})/{slug}.md
5. Copy images to: {website-repo}/public/images/blog/{slug}/
6. Git commit: git add . && git commit -m "Add blog post: {slug}"
7. Git push: git push origin main (triggers Easypanel auto-deploy)
8. Return deployment URL
📁 Output Examples
Facebook Post Output:
{
"channel": "facebook",
"topic": "บริการ podcast",
"language": "th",
"generated_at": "2026-03-08T14:30:00+07:00",
"variations": [
{
"id": "fb_post_1",
"primary_text": "คุณกำลังมองหาวิธีเริ่มต้น podcast ใช่ไหม? 🎙️\n\nตอนนี้ใครๆ ก็ทำ podcast ได้ง่ายๆ แค่มีเครื่องมือที่เหมาะสม เราช่วยคุณได้ตั้งแต่เริ่มจนถึงเผยแพร่\n\n#podcast #podcastไทย #สร้างpodcast",
"headline": "เริ่มต้น podcast ของคุณวันนี้",
"cta": "เรียนรู้เพิ่มเติม",
"hashtags": ["#podcast", "#podcastไทย", "#สร้างpodcast"],
"image": {
"type": "generated",
"path": "output/บริการ-podcast/facebook/images/variation_1.png",
"prompt": "Professional podcast studio setup with microphone and headphones, modern aesthetic, Thai-friendly design"
},
"api_ready": {
"message": "Matches Meta Graph API /act_id/adcreatives structure",
"endpoint": "POST /v18.0/act_{ad_account_id}/adcreatives"
}
}
]
}
Google Ads Output:
{
"channel": "google_ads",
"topic": "podcast hosting",
"language": "th",
"generated_at": "2026-03-08T14:30:00+07:00",
"responsive_search_ads": [
{
"id": "ga_rsa_1",
"headlines": [
{"text": "บริการ Podcast Hosting", "pin": false},
{"text": "เริ่มต้นฟรี 14 วัน", "pin": false},
{"text": "เผยแพร่ทุกแพลตฟอร์ม", "pin": false},
{"text": "ง่าย รวดเร็ว มืออาชีพ", "pin": false},
{"text": "รองรับภาษาไทย", "pin": false}
],
"descriptions": [
{"text": "แพลตฟอร์ม podcast ที่ครบวงจรที่สุด เริ่มต้นสร้าง podcast ของคุณวันนี้"},
{"text": "เผยแพร่ Apple Podcasts, Spotify, YouTube Music ได้ในคลิกเดียว"}
],
"keywords": ["podcast hosting", "host podcast", "บริการ podcast", "แพลตฟอร์ม podcast"],
"negative_keywords": ["ฟรี", "download", "mp3"],
"ad_extensions": {
"sitelinks": [
{"text": "เริ่มฟรี 14 วัน", "url": "/free-trial"},
{"text": "ดูคุณสมบัติ", "url": "/features"}
],
"callouts": ["รองรับภาษาไทย", "ทีมซัพพอร์ท 24/7", "ยกเลิกเมื่อไหร่ก็ได้"]
},
"api_ready": {
"matches": "Google Ads API v15.0",
"endpoint": "POST /google.ads.googleads.v15.services/GoogleAdsService:Mutate",
"resource": "AdGroupAd"
}
}
]
}
Blog Post Output:
---
title: "บริการ Podcast Hosting ที่ดีที่สุดปี 2026: คู่มือครบวงจร"
description: "เปรียบเทียบ 10+ บริการ podcast hosting พร้อมข้อมูลจริง ช่วยคุณเลือกแพลตฟอร์มที่เหมาะกับ podcast ของคุณ"
keywords: ["podcast hosting", "บริการ podcast", "แพลตฟอร์ม podcast", "host podcast"]
slug: podcast-hosting-best-2026
lang: th
category: guides
tags: [podcast, hosting, review]
created: 2026-03-08
images:
- src: /images/blog/podcast-hosting-best-2026/hero.png
alt: "เปรียบเทียบบริการ podcast hosting"
---
# บริการ Podcast Hosting ที่ดีที่สุดในปี 2026
คุณกำลังมองหาบริการ podcast hosting ที่ใช่อยู่ใช่ไหม? 🎙️
บทความนี้จะเปรียบเทียบแพลตฟอร์มยอดนิยม 10+ เจ้า พร้อมข้อมูลจริงจากการทดสอบ...
[Content continues for 2000+ words]
## สรุป
เลือกบริการ podcast hosting ที่เหมาะกับคุณที่สุด...
**พร้อมเริ่ม podcast ของคุณหรือยัง?** [สมัครฟรี 14 วัน →](/signup)
🔧 Technical Implementation
Thai Language Processing:
from pythainlp import word_tokenize, sent_tokenize
from pythainlp.util import normalize
def count_thai_words(text: str) -> int:
"""Count Thai words (no spaces between words)"""
tokens = word_tokenize(text, engine="newmm")
return len([t for t in tokens if t.strip() and not t.isspace()])
def calculate_thai_keyword_density(text: str, keyword: str) -> float:
"""Calculate keyword density for Thai text"""
text_normalized = normalize(text)
keyword_normalized = normalize(keyword)
count = text_normalized.count(keyword_normalized)
word_count = count_thai_words(text)
return (count / word_count * 100) if word_count > 0 else 0
def detect_content_language(text: str) -> str:
"""Detect if content is Thai or English"""
thai_chars = sum(1 for c in text if '\u0E00' <= c <= '\u0E7F')
total_chars = len(text)
thai_ratio = thai_chars / total_chars if total_chars > 0 else 0
if thai_ratio > 0.3:
return 'th'
return 'en'
Image Handling:
import os
import glob
from pathlib import Path
def find_product_images(product_name: str, website_repo: str) -> List[str]:
"""Find existing product images in website repo"""
extensions = ['.jpg', '.jpeg', '.png', '.webp']
found_images = []
search_patterns = [
f"**/*{product_name}*{{ext}}" for ext in extensions
] + [
f"public/images/**/*{{ext}}",
f"src/assets/**/*{{ext}}"
]
for pattern in search_patterns:
matches = glob.glob(os.path.join(website_repo, pattern), recursive=True)
found_images.extend(matches)
return found_images[:10] # Return top 10 matches
def save_image_for_channel(image_data: bytes, topic: str, channel: str) -> str:
"""Save generated/edited image to correct location"""
if channel == 'blog':
# Blog images go to website repo
output_dir = os.path.join(website_repo, 'public/images/blog', topic_slug)
else:
# Social/Ads images go to separate folder
output_dir = os.path.join('output', topic_slug, channel, 'images')
os.makedirs(output_dir, exist_ok=True)
image_path = os.path.join(output_dir, f"variation_{variation_num}.png")
with open(image_path, 'wb') as f:
f.write(image_data)
return image_path
Website-Creator Integration:
def publish_blog_to_astro(article_md: str, website_repo: str) -> Dict:
"""
Publish blog post to Astro content collections
Returns deployment status
"""
# Parse frontmatter
frontmatter = parse_frontmatter(article_md)
# Detect language
lang = detect_content_language(article_md)
# Generate slug
slug = generate_slug(frontmatter['title'], lang)
# Determine output path
output_path = os.path.join(
website_repo,
'src/content/blog',
f'({lang})',
f'{slug}.md'
)
# Ensure directory exists
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# Write article
with open(output_path, 'w', encoding='utf-8') as f:
f.write(article_md)
# Copy images if any
if 'images' in frontmatter:
for img in frontmatter['images']:
# Copy from temp location to website repo
dest_path = os.path.join(website_repo, 'public', img['src'].lstrip('/'))
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
shutil.copy(img['local_path'], dest_path)
# Git commit and push
subprocess.run(['git', 'add', '.'], cwd=website_repo, check=True)
subprocess.run(['git', 'commit', '-m', f'Add blog post: {slug}'], cwd=website_repo, check=True)
subprocess.run(['git', 'push', 'origin', 'main'], cwd=website_repo, check=True)
# Return deployment info
return {
'published': True,
'slug': slug,
'language': lang,
'path': output_path,
'deployment_url': f"https://your-domain.com/blog/{slug}" if lang == 'en' else f"https://your-domain.com/th/{slug}"
}
📐 Channel Specifications
Facebook:
- Primary text: 125-250 chars (Thai can be longer)
- Headline: 100 chars max
- Hashtags: 3-5 recommended
- Image: 1200x630 (1.91:1)
- Variations: 5
Facebook Ads:
- Primary text: 125 chars recommended (5000 max)
- Headline: 40 chars
- Description: 90 chars
- CTA: Button selection
- Image: 1200x628 (1.91:1) or 1080x1080 (1:1)
- API ready: Yes (Meta Graph API)
Google Ads:
- Headlines: 15 variations, 30 chars each
- Descriptions: 4 variations, 90 chars each
- Keywords: 15-20 suggested
- Negative keywords: 10-15 suggested
- Ad extensions: Sitelinks, callouts, structured snippets
- API ready: Yes (Google Ads API)
Blog:
- Word count: 1500-3000 (Thai), 2000-3000 (English)
- Keyword density: 1.0-1.5% (Thai), 1.5-2% (English)
- Meta title: 50-60 chars
- Meta description: 150-160 chars
- Images: Saved to website repo
- Format: Markdown with frontmatter
- Astro ready: Yes (content collections)
X/Twitter:
- Hook tweet: 280 chars
- Body tweets: 2-8 tweets, 280 chars each
- CTA tweet: 280 chars
- Hashtags: 2-3 per tweet
- Thread title: Optional
⚙️ Environment Variables
Required (in unified .env or project .env):
# Chutes AI (for image generation/editing)
CHUTES_API_TOKEN=your_token_here
# Google Analytics 4 (optional)
GA4_PROPERTY_ID=G-XXXXXXXXXX
GA4_CREDENTIALS_PATH=path/to/ga4-credentials.json
# Google Search Console (optional)
GSC_SITE_URL=https://yourdomain.com
GSC_CREDENTIALS_PATH=path/to/gsc-credentials.json
# DataForSEO (optional)
DATAFORSEO_LOGIN=your_login
DATAFORSEO_PASSWORD=your_password
# Umami Analytics (optional, if self-hosted)
UMAMI_API_URL=https://analytics.yourdomain.com
UMAMI_API_KEY=your_api_key
🚀 Commands
Generate Multi-Channel Content:
python3 skills/seo-multi-channel/scripts/generate_content.py \
--topic "บริการ podcast hosting" \
--channels facebook facebook_ads google_ads blog x \
--website-repo ./my-website \
--auto-publish true
Generate for Specific Channel:
# Facebook Ads only
python3 skills/seo-multi-channel/scripts/generate_content.py \
--topic "podcast microphone" \
--channels facebook_ads \
--product-name "PodMic Pro" \
--website-repo ./my-website
Publish Existing Blog:
python3 skills/seo-multi-channel/scripts/publish_blog.py \
--article drafts/podcast-guide-2026.md \
--website-repo ./my-website
📊 Quality Scoring
Each piece of content is scored before output:
-
Keyword Optimization (0-25 points)
- Density, placement, variations
-
Brand Voice Alignment (0-25 points)
- Tone, terminology, style
-
Channel Fit (0-25 points)
- Length, format, CTA appropriateness
-
Thai Language Quality (0-25 points)
- Natural phrasing, formality level, no awkward translations
Minimum score: 70/100 to publish. Below 70 → auto-revise or flag for review.
⚠️ Important Notes
-
Thai Word Counting: Thai has no spaces between words. Uses PyThaiNLP for accurate counting.
-
Formality Detection: Auto-detects from brand voice context. Defaults to casual for social, normal for blog.
-
Image Handling:
- Product content → Browse repo first → Edit with image-edit
- Non-product → Generate fresh with image-generation
- Blog images → Website repo
- Social/Ads images → Separate folder
-
API Ready: Output structures match Google Ads and Meta Ads API schemas for future integration.
-
Data Services Optional: Skips unconfigured services (GA4, GSC, DataForSEO, Umami).
-
Per-Project Context: Each website has its own context/ folder with brand voice, keywords, guidelines.
🔄 Integration with Other Skills
- image-generation: Called for fresh images (non-product content)
- image-edit: Called for product images (browse repo first)
- website-creator: Blog posts published to Astro content collections
- seo-analyzers: Quality scoring and Thai language analysis
- seo-data: Performance data for content optimization
- seo-context: Context file management
✅ Success Criteria
- ✅ Content generated for all selected channels
- ✅ Thai language processing accurate (word count, keyword density)
- ✅ Product images found/enhanced or user asked to provide
- ✅ Fresh images generated for non-product content
- ✅ Blog posts published to Astro (if enabled)
- ✅ Git commit + push successful (triggers auto-deploy)
- ✅ Output structures API-ready for future integration
- ✅ Quality scores ≥ 70/100 for all content
Use this skill when you need to create multi-channel marketing content from a single topic with full Thai language support and automatic image handling.