Developing a Bot for Automatic Product Publishing from Website to Instagram
Bot automatically takes products from website catalog and publishes them to Instagram — with photo, description, price, hashtags. Without manual content manager work, without data duplication, without delays.
How It Works Technically
Instagram doesn't provide direct public API for posting from personal account. Official way — Instagram Graph API through Meta Business Suite. It allows publishing photos, carousels, and Reels for business accounts and creator accounts.
Integration scheme:
- Website (CMS/store) → task queue (Redis + BullMQ or Laravel Queue)
- Worker gets task → prepares media and text
- Request to Graph API: upload image → create container → publish
POST https://graph.facebook.com/v19.0/{ig-user-id}/media
?image_url=https://cdn.example.com/products/123.jpg
&caption=New%3A%20Sneakers%20Air%20Max%0A%0APrice%3A%201290%20rubles%0A%0A%23sneakers%20%23shoes
&access_token={PAGE_ACCESS_TOKEN}
POST https://graph.facebook.com/v19.0/{ig-user-id}/media_publish
?creation_id={container-id}
&access_token={PAGE_ACCESS_TOKEN}
For carousel publishing (multiple product photos) — child containers are created first for each image, then parent container of type CAROUSEL.
What's Needed from Client
- Instagram Business or Creator account
- Connected Facebook Page
- Meta app with rights
instagram_basic,instagram_content_publish,pages_read_engagement - Long-lived access token (valid 60 days, auto-refresh needed)
Token auto-refresh is implemented via scheduled job — 7 days before expiration token is exchanged for new one via /oauth/access_token?grant_type=fb_exchange_token.
Generating Post Caption
Caption template assembled from product fields:
def build_caption(product):
lines = [
f"✨ {product['name']}",
"",
product['short_description'][:200] if product['short_description'] else "",
"",
f"💰 Price: {product['price']} {product['currency']}",
]
if product.get('sale_price'):
lines.append(f"🔥 Sale Price: {product['sale_price']} {product['currency']}")
lines += ["", " ".join(f"#{tag}" for tag in product['tags'][:10])]
return "\n".join(line for line in lines if line is not None)
Caption length — up to 2200 characters, hashtags — up to 30. Exceeded limit handled by description truncation, not hashtags.
Publishing Triggers
| Trigger | Mechanism |
|---|---|
| New product in "published" status | Webhook / Observer on Product model |
| Price change by X% | price_changed_at field + cron comparison |
| Scheduled posting | instagram_scheduled_at field in product |
| Manual run from admin | Button → API endpoint → task in queue |
Deduplication and Limits
Graph API allows up to 25 publications per day per account (carousel counts as 1). Bot maintains instagram_posts table with fields product_id, ig_media_id, published_at. Before posting checks:
- wasn't product published in last N days
- daily limit not exceeded
- image available at URL (HEAD request with 5s timeout)
Implementation Timeline
Basic bot with single photo publishing — 5–7 business days. Carousel, caption templating, admin panel, API retry logic — additional 3–5 days.







