Social Integration
This document covers the social media integration capabilities of the CRM & Marketing Platform.
Supported Platforms
| Platform | API | Features |
|---|---|---|
| Graph API | Pages, Posts, Events | |
| Graph API (via FB) | Business posts, Stories | |
| Twitter/X | API v2 | Tweets, Media |
| Marketing API | Company pages (future) |
Social Connection Flow
┌─────────────────────────────────────────────────────────────────┐
│ SOCIAL CONNECTION OAUTH FLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Club Admin CRM Platform Facebook │
│ │ │ │ │
│ │ 1. Click "Connect FB" │ │ │
│ │─────────────────────────▶│ │ │
│ │ │ │ │
│ │ │ 2. Redirect to OAuth │ │
│ │◀─────────────────────────│───────────────────────▶│ │
│ │ │ │ │
│ │ 3. Authorize app │ │ │
│ │──────────────────────────────────────────────────▶│ │
│ │ │ │ │
│ │ 4. Callback with token │ │ │
│ │◀─────────────────────────│◀───────────────────────│ │
│ │ │ │ │
│ │ │ 5. Store encrypted │ │
│ │ │ token │ │
│ │ │─────────┐ │ │
│ │ │ │ │ │
│ │ │◀────────┘ │ │
│ │ │ │ │
│ │ 6. Connection saved │ │ │
│ │◀─────────────────────────│ │ │
│ │
└─────────────────────────────────────────────────────────────────┘
OAuth Configuration
Facebook
Permissions requested:
- pages_manage_posts
- pages_read_engagement
- pages_read_user_content
- instagram_basic (for IG via FB)
- instagram_content_publish
Instagram (via Facebook)
Instagram Business accounts are connected through Facebook Graph API.
Twitter
Scopes requested:
- tweet.read
- tweet.write
- users.read
- offline.access
Token Management
Security
- Access tokens encrypted at rest (AES-256)
- Refresh tokens stored separately
- Decrypted only at publish time
- Never exposed in API responses
Token Refresh
// Automatic refresh before expiry
async refreshTokenIfNeeded(connectionId: string): Promise<void> {
const connection = await this.getConnection(connectionId);
if (connection.tokenExpiry && connection.tokenExpiry < addDays(now(), 7)) {
const newTokens = await this.refreshToken(connection);
await this.updateTokens(connectionId, newTokens);
}
}
Social Post Publishing
SocialPost Model
interface SocialPost {
id: string;
tenantId: string;
connectionId: string; // Which social account
campaignId?: string; // Optional campaign link
content: string; // Post text
mediaUrls: string[]; // Images/videos
linkUrl?: string; // Link preview
status: SocialPostStatus; // DRAFT, SCHEDULED, PUBLISHED
scheduledAt?: Date;
publishedAt?: Date;
platformPostId?: string; // ID returned by platform
// Engagement metrics (synced)
likes: number;
comments: number;
shares: number;
reach: number;
}
Post Status Flow
DRAFT ──▶ SCHEDULED ──▶ PUBLISHING ──▶ PUBLISHED
│ │ │ │
▼ ▼ ▼ ▼
Edit Cancel (auto) Sync metrics
FAILED ◀── On error
Publishing to Platforms
Facebook
const response = await fetch(
`https://graph.facebook.com/v18.0/${pageId}/feed`,
{
method: 'POST',
body: JSON.stringify({
message: content,
link: linkUrl,
access_token: decryptedToken,
}),
}
);
Instagram
// Two-step process for media posts
// 1. Create media container
const container = await createMediaContainer({
image_url: mediaUrl,
caption: content,
});
// 2. Publish container
await publishMedia(container.id);
Twitter
const response = await fetch(
'https://api.twitter.com/2/tweets',
{
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({ text: content }),
}
);
Engagement Sync
Periodically sync engagement metrics from platforms:
async syncEngagement(postId: string): Promise<void> {
const post = await this.getPost(postId);
const connection = await this.getConnection(post.connectionId);
const metrics = await this.fetchMetrics(
connection.platform,
post.platformPostId
);
await this.updatePost(postId, {
likes: metrics.likes,
comments: metrics.comments,
shares: metrics.shares,
reach: metrics.reach,
impressions: metrics.impressions,
engagementSyncedAt: new Date(),
});
}
Sync Frequency
| Timing | Frequency |
|---|---|
| First 24 hours | Every hour |
| Days 2-7 | Every 6 hours |
| After 7 days | Daily |
Content Calendar
Features (Phase 5)
- Visual calendar view
- Drag-and-drop scheduling
- Cross-platform preview
- Bulk scheduling
- Recurring posts
Calendar View
December 2024
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
│ │ 📘 │ │ 📸 │ │ 📘 │ │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ 8 │ 9 │ 10 │ 11 │ 12 │ 13 │ 14 │
│ │ 📘📸│ │ │ 🐦 │ 📘 │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
📘 Facebook 📸 Instagram 🐦 Twitter
Rate Limits
| Platform | Limit | Period |
|---|---|---|
| 200 posts | 24 hours (per page) | |
| 25 posts | 24 hours | |
| 200 tweets | 15 minutes |
Handling Limits
if (error.code === 'RATE_LIMIT_EXCEEDED') {
// Reschedule for later
await reschedulePost(postId, addHours(now(), 1));
}
Error Handling
| Error | Action |
|---|---|
| Invalid token | Mark connection inactive, notify admin |
| Rate limited | Reschedule post |
| Content rejected | Mark failed, notify creator |
| Network error | Retry with backoff |