Skip to main content

Social Integration

This document covers the social media integration capabilities of the CRM & Marketing Platform.


Supported Platforms

PlatformAPIFeatures
FacebookGraph APIPages, Posts, Events
InstagramGraph API (via FB)Business posts, Stories
Twitter/XAPI v2Tweets, Media
LinkedInMarketing APICompany 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

TimingFrequency
First 24 hoursEvery hour
Days 2-7Every 6 hours
After 7 daysDaily

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

PlatformLimitPeriod
Facebook200 posts24 hours (per page)
Instagram25 posts24 hours
Twitter200 tweets15 minutes

Handling Limits

if (error.code === 'RATE_LIMIT_EXCEEDED') {
// Reschedule for later
await reschedulePost(postId, addHours(now(), 1));
}

Error Handling

ErrorAction
Invalid tokenMark connection inactive, notify admin
Rate limitedReschedule post
Content rejectedMark failed, notify creator
Network errorRetry with backoff