Hyphen User Guides

Social Media Management

Complete guide to connecting social accounts, creating and scheduling posts, running campaigns, and tracking engagement

Version 1.2|Updated 2026-06-23|Marketing Teams, Social Media Managers, Operations

1. Feature Overview

The Social Media Management module lets your team create, schedule, and publish social media posts to Facebook, Instagram, and X (Twitter) directly from the Hyphen Admin Console. You can manage all your social accounts in one place, schedule posts in advance, run multi-platform campaigns, track performance with built-in analytics, and retry posts that fail to publish.

It is built on four moving parts that you will see referenced throughout this guide:

  1. OAuth account linking — you authorise each platform once; the platform stores an encrypted access token (and refresh token where supported) and uses it on your behalf.
  2. Posts in PostgreSQL — every post (single or multi-platform) is a row in the SocialPost table with a status (draft → scheduled → publishing → published / failed / cancelled).
  3. Cron-driven publishing — a background job (publish-social) runs every 5 minutes and pushes due scheduled posts to the live platform APIs.
  4. Metrics sync — a second job (sync-social-metrics) runs hourly and pulls engagement numbers back into the SocialMetrics table to power Analytics.

The end-to-end flow looks like this:

End-to-end data flow: compose in the Admin Console, persist to Postgres, publish via cron, sync metrics back, surface in Analytics.

The deep technical walkthrough of this flow lives in How It Works (Behind the Scenes) below.

What you can do:

  • Connect your organisation's Facebook Pages, Instagram Business accounts, and X (Twitter) accounts
  • Create posts for a single platform or multiple platforms at once
  • Add images, hashtags, links, and UTM tracking parameters
  • Schedule posts for future dates and times, or publish immediately
  • View and manage your publishing queue on a visual calendar
  • Organise posts into campaigns and track campaign goals
  • View posting history and retry any posts that failed
  • Analyse engagement metrics, top-performing content, best posting times, and hashtag performance
  • Export analytics data as CSV or JSON
  • Access an executive dashboard with high-level KPIs and period comparisons

Automation: The system automatically publishes scheduled posts every 5 minutes and syncs engagement metrics from each platform every hour. You do not need to do anything manually for these — they run in the background.


How It Works (Behind the Scenes)

This section explains what actually happens under the hood when you connect an account, compose a post, and let the platform publish it. You do not need to understand this to use the feature, but it helps when troubleshooting a failed post or a metrics gap.

1. Connecting an account. When you click Connect for a platform, the Admin Console redirects you to that platform's OAuth consent screen (Meta Graph for Facebook/Instagram, X v2 for X). On success, the platform redirects back to a callback route (/api/social/meta/callback or /api/social/x/callback), which exchanges the authorisation code for an access token (and a refresh token where supported). These tokens are encrypted and stored as a SocialAccount row, along with the platform user/page ID, granted scopes, follower count, and a status (connected, expired, error, or disconnected).

2. Composing a post. Whatever you type in the composer is validated (Zod plus per-platform rules such as character limits and media counts) and saved as a SocialPost row in PostgreSQL with status = draft. A multi-platform post creates one SocialPost per target account, all sharing a postGroupId so they can be managed as a group. If you click Publish Now, the post goes straight to the publisher; if you schedule it, scheduledFor is set and status becomes scheduled.

3. Publishing. The publish-social cron job runs every 5 minutes. It finds every SocialPost whose status = scheduled and whose scheduledFor time has passed, flips it to publishing, and calls the live platform API using the account's stored token. On success it records platformPostId, platformUrl, publishedAt, and sets status = published. On failure it records errorMessage, increments retryCount, and sets status = failed (retried up to 3 times).

4. Syncing metrics. The sync-social-metrics cron job runs hourly. For recently published posts it calls each platform's insights API and writes the numbers (impressions, reach, engagements, likes, comments, shares, saves, clicks, video views, and a derived engagement rate) into the linked SocialMetrics row. Those figures feed the Analytics and Executive dashboards.

Behind the scenes: posts persist to Postgres, the publish-social cron pushes them to the platform APIs, and the sync-social-metrics cron pulls engagement data back for analytics.

Concepts: Account Linking, Posts & Scheduling

Account linking (OAuth). Each social account is connected once via OAuth. The platform never stores your platform password — only the encrypted tokens returned by Facebook/Instagram (Meta) or X. A token can expire (Meta long-lived tokens last ~60 days); the Refresh action obtains a fresh token, and the check-token-expiry/refresh flows warn you before a token lapses. One connected platform account = one SocialAccount row, uniquely keyed by (platform, platformId).

Single vs multi-platform posts. A single-platform post is one SocialPost tied to one SocialAccount. A multi-platform post (the compose-multi flow) creates several SocialPost rows — one per selected account — sharing a common postGroupId. Each row publishes independently, so one platform can succeed while another fails; you retry only the failed one.

Scheduling. A post is either Publish Now (handed to the publisher immediately) or Scheduled (scheduledFor set, status = scheduled). The publish-social cron is the only thing that moves a scheduled post forward, so the actual publish time is accurate to within the 5-minute cron window.

Metrics sync. After a post is published, the sync-social-metrics cron periodically refreshes its SocialMetrics. Numbers are not instant — expect them to populate within an hour of publishing and to keep updating for several days.

Lifecycle of a social post from draft through scheduling, publishing, and the terminal published / failed / cancelled states.

2. Who Should Use This Feature

RoleWhat You Can Do
AdminFull access — connect/disconnect accounts, create/edit/delete/publish posts, manage campaigns, view all analytics including the Executive Dashboard
EditorFull access — same as Admin for social media features, including connecting accounts, publishing, campaigns, and Executive Dashboard
Publishing TeamCreate, edit, publish, and schedule posts. Create and edit campaigns. View analytics. Cannot disconnect accounts or delete campaigns
Marketing ManagerCreate, edit, and schedule posts (cannot directly publish). Create and edit campaigns. View analytics. Cannot connect/disconnect accounts
Chief EditorRead-only — can view posts and analytics but cannot create, edit, or publish

Roles without social media access: Moderator, Sub-Editor, Designer, Author, Sales Manager. If you need access, ask your Admin to update your role.


3. Before You Begin

Before you can use Social Media features, the following must be in place:

3.1 Platform Credentials (Admin/DevOps Responsibility)

Social publishing requires API credentials from each platform. These are configured as environment variables by your technical team:

PlatformRequired CredentialsWhere to Get Them
Facebook & InstagramMETA_APP_ID, META_APP_SECRETMeta for Developers — create a Business app with the Facebook Login product. Callback: {APP_URL}/api/social/meta/callback
X (Twitter)X_API_KEY, X_API_SECRETX Developer Portal — create an OAuth 2.0 app with PKCE. Callback: {APP_URL}/api/social/x/callback

Naming note: Despite the names, X_API_KEY / X_API_SECRET hold your OAuth 2.0 Client ID and Client Secret (not the legacy v1.1 consumer key/secret). The callback URLs can be overridden with the optional META_REDIRECT_URI / X_REDIRECT_URI variables; otherwise they default to NEXT_PUBLIC_APP_URL + the callback path.

Additionally, an ENCRYPTION_KEY environment variable (a 64-character hex string) must be set to securely encrypt account access/refresh tokens at rest in the database.

No credentials yet? The platform has a Demo Mode (SOCIAL_DEMO_MODE=true) that lets you test the full workflow with simulated accounts and publishing. Ask your technical team to enable it.

3.2 Check Configuration Status

  1. Navigate to Social Publishing (sidebar menu)
  2. If credentials are not configured, you will see a configuration notice indicating which providers are not set up
  3. You can also check /api/social/config which shows the setup status for each provider

3.3 Cron Jobs Must Be Active

Two automated jobs power the social media system:

JobRuns EveryWhat It Does
Publish Social5 minutesPublishes posts that have reached their scheduled time
Sync Social Metrics1 hourFetches engagement data (likes, comments, shares, impressions) from each platform

These are configured in vercel.json and need to be triggered by your hosting platform (e.g., Vercel Cron). The exact schedules are:

Cron routeSchedule (cron expression)Frequency
/api/cron/publish-social*/5 * * * *Every 5 minutes
/api/cron/sync-social-metrics0 * * * *Top of every hour

Both routes require the cron secret header (CRON_SECRET) to authenticate. Confirm with your technical team that these are running.

3.4 Permissions

Confirm your user role has the necessary social media permissions (see Section 2). If you see an "Access Restricted" message on any social page, contact your Admin.


4. Key Terms in Simple Language

TermWhat It Means
Social AccountA Facebook Page, Instagram Business account, or X (Twitter) account that you have connected to the platform
PostA piece of content (text, images, hashtags, link) that gets published to a social platform
Multi-Platform PostA single piece of content published to multiple platforms at once, with optional per-platform customisations
Post GroupA set of posts created together in a multi-platform batch — they share a postGroupId so you can track them as a unit
DraftA post that has been saved but not yet scheduled or published
ScheduledA post set to automatically publish at a specific future date and time
PublishedA post that has been successfully sent to the platform
FailedA post that the system tried to publish but could not — you can retry it
CancelledA scheduled post that was cancelled before it published
PublishingA transitional state — the system is actively sending the post to the platform right now
CampaignA named grouping of related posts (e.g., "Spring Launch 2026") with optional goals for impressions, engagements, and clicks
UTM ParametersTracking tags added to links so you can measure which social posts drive website traffic
Engagement RateA percentage showing how many people who saw your post interacted with it (engagements ÷ reach × 100)
Staggered SchedulingPublishing the same content to different platforms at different times, spaced apart by a set number of minutes
Token ExpirySocial platform credentials expire after a period (Meta: ~60 days, X: hours). When expired, the account cannot publish until refreshed
Demo ModeA testing mode where accounts and publishing are simulated — no real posts go to social platforms
RetryRe-attempting to publish a failed post (maximum 3 retries allowed)

5. Step-by-Step Setup Guide

Social media accounts
Connect and manage your Facebook, Instagram, and X (Twitter) accounts from a single dashboard.

5.1 Connecting a Facebook Page

Prerequisites: Meta App credentials configured, you have Admin or Editor role, you are an admin of the Facebook Page you want to connect.

  1. Go to Social Publishing from the sidebar menu
  2. Look for the account connection area or navigate to your social accounts settings
  3. Click Connect Facebook (or the Facebook option)
  4. You will be redirected to Facebook's authorisation screen
  5. Log in with the Facebook account that manages the Page
  6. Grant all requested permissions — the platform requests:
    • pages_show_list — to see your Pages
    • pages_manage_posts — to publish posts
    • instagram_basic — to see linked Instagram accounts
    • instagram_content_publish — to publish to Instagram
    • instagram_manage_insights — to read Instagram metrics
    • business_management — to manage business assets
  7. Select the Facebook Page(s) you want to connect
  8. Click Continue / Done on Facebook's screen
  9. You will be redirected back to the Admin Console
  10. Your Facebook Page should now appear with status Connected

What happens behind the scenes: The platform exchanges the short-lived token for a long-lived token (~60 days), fetches your managed Pages and any linked Instagram Business accounts, and stores the encrypted credentials.

5.2 Connecting an Instagram Business Account

Prerequisites: Your Instagram account must be a Business or Creator account linked to a Facebook Page. Instagram connections come through the Meta (Facebook) OAuth flow.

  1. Follow the same steps as connecting a Facebook Page (Section 5.1)
  2. During the Facebook authorisation, ensure you grant Instagram permissions
  3. After the callback, the platform automatically detects Instagram Business accounts linked to your Facebook Pages
  4. Connected Instagram accounts will appear alongside your Facebook Pages

Important: Personal Instagram accounts cannot be connected. Only Instagram Business or Creator accounts linked to a Facebook Page are supported.

5.3 Connecting an X (Twitter) Account

Prerequisites: X API credentials configured, you have Admin or Editor role.

  1. Go to Social Publishing from the sidebar menu
  2. Click Connect X (Twitter) (or the X/Twitter option)
  3. You will be redirected to X's authorisation screen
  4. Log in with the X account you want to connect
  5. Authorise the application — the platform requests:
    • tweet.read — to read tweets
    • tweet.write — to post tweets
    • users.read — to read profile information
    • offline.access — to maintain access via refresh tokens
  6. Click Authorize app on X's screen
  7. You will be redirected back to the Admin Console
  8. Your X account should now appear with status Connected

Note on token expiry: X tokens expire after a few hours, but the platform automatically uses a refresh token to get new access tokens. If you see an "Expired" status, use the Refresh action on the account.

5.4 Understanding Account Connection Status

StatusWhat It MeansWhat to Do
Connected (green)Account is active and ready to publishNothing — you're good to go
Expired (yellow/warning)The access token has expiredClick Refresh on the account to renew the token. If that fails, disconnect and reconnect the account
DisconnectedAccount was manually disconnectedReconnect if you want to use it again
Error (red)Something went wrong with the connectionCheck the error message. Usually requires disconnecting and reconnecting

5.5 Refreshing an Account Token

  1. Find the account in your social accounts list
  2. Click the Refresh button/action on the account
  3. For X: The platform uses the stored refresh token to get a new access token
  4. For Meta: The platform validates the current token is still valid
  5. The status should update to Connected with a new expiry date

5.6 Disconnecting an Account

  1. Find the account you want to remove
  2. Click Disconnect or the delete action
  3. If the account has scheduled or publishing posts, you will see a confirmation warning with the count of affected posts. You must confirm with Force Disconnect to proceed — this will delete all associated posts
  4. If there are no pending posts, the account is removed immediately

Configuration Reference

This reference lists everything that is configurable, where it lives, and who can set it. The platform credentials are backend/environment settings (set once by an Admin or DevOps); the post and campaign fields are set in the UI by anyone with social access.

Platform connection (OAuth app credentials)

These environment variables enable each platform integration. Without them, the matching Connect button is disabled. They are set on the server, never in the UI.

Field / OptionWhat it doesTypeMandatory?DefaultWhere configuredRole
META_APP_IDMeta (Facebook/Instagram) OAuth app IDenv var (string)Yes for FB/IGBackend .env / hosting envAdmin / DevOps
META_APP_SECRETMeta OAuth app secret for token exchangeenv var (secret)Yes for FB/IGBackend .env / hosting envAdmin / DevOps
X_API_KEYX (Twitter) OAuth client IDenv var (string)Yes for XBackend .env / hosting envAdmin / DevOps
X_API_SECRETX OAuth client secretenv var (secret)Yes for XBackend .env / hosting envAdmin / DevOps
X_REDIRECT_URIX OAuth callback URLenv var (string)No${NEXT_PUBLIC_APP_URL}/api/social/x/callbackBackend .env / hosting envAdmin / DevOps
NEXT_PUBLIC_APP_URLBase URL used to build OAuth redirect URIsenv var (string)YesBackend .env / hosting envAdmin / DevOps
Account scopesPermissions requested at consent (stored in SocialAccount.scopes)string[]Set by platformper integrationGranted on the OAuth consent screenAdmin / Editor

Post composer fields

Set in the UI at Social → Compose (single) or Social → Compose Multi (multi-platform). Stored on the SocialPost model.

Field / OptionWhat it doesTypeMandatory?DefaultWhere configuredRole
Account(s)Target platform account(s); multiple = multi-platform group (postGroupId)selectYesCompose / Compose MultiPublishing+
CopyThe post text/bodytextYesComposerPublishing+
MediaAttached images/videos (mediaUrls)string[] (URLs)No[]Composer media pickerPublishing+
HashtagsTags appended/tracked (hashtags)string[]No[]ComposerPublishing+
Link URLURL being shared (linkUrl)stringNoComposerPublishing+
UTM source / medium / campaign / contentTracking params merged into trackedUrlstringNoComposer (UTM panel)Publishing+
Article / Submission linkAssociates post with a Strapi article or workflow submissionidNoCompose from article/workflowPublishing+
CampaignAssigns post to a SocialCampaignselectNoComposerPublishing+

Scheduling fields

Field / OptionWhat it doesTypeMandatory?DefaultWhere configuredRole
Publish modePublish Now vs SchedulechoiceYesScheduleComposerPublishing+ (publish requires Publishing/Editor/Admin)
Scheduled forDate/time the publish-social cron will publish (scheduledFor)datetimeRequired if schedulingComposer / CalendarPublishing / Marketing Mgr+
StatusLifecycle state (draft, scheduled, publishing, published, failed, cancelled)enum (system)AutodraftManaged by system
Retry countAutomatic publish retries (max 3)int (system)Auto0Managed by system

Campaign fields

Set in the UI at Social → Campaigns. Stored on the SocialCampaign model.

Field / OptionWhat it doesTypeMandatory?DefaultWhere configuredRole
NameCampaign namestringYesCampaignsPublishing+
DescriptionFree-text notestextNoCampaignsPublishing+
Start / End dateCampaign window (startDate, endDate)datetimeYesCampaignsPublishing+
Statusdraft, active, paused, completed, archivedenumYesdraftCampaignsPublishing+
Goal impressions / engagements / clicksTargets tracked against actualsintNoCampaignsPublishing+
Is templateReuse campaign as a templatebooleanNofalseCampaignsPublishing+

Cron schedules (system). publish-social runs every 5 minutes (*/5 * * * *); sync-social-metrics runs hourly (0 * * * *). Both are configured in vercel.json and require no manual action.


6. Day-to-Day Operations

Social media post composer
1
2
3
4
The post composer — create and schedule posts across platforms
1Platform selector — choose Facebook, Instagram, X, or multi-platform
2Content area — write your post text, add hashtags and mentions
3Media upload — attach images to your post
4Schedule controls — publish now or pick a future date and time

6.1 Creating a Single-Platform Post

  1. Navigate to Social PublishingPosts (or click New Post / Create Post from the dashboard)
  2. You will land on the Compose page in Single Post mode

Left Column — Post Content:

  1. Select Platform — Choose the social account you want to post to (e.g., "Facebook — Brand Page"). Each account shows its platform icon and name
  2. Write Your Post — Type your content in the text area. A character counter shows your remaining characters
    • Twitter/X: Maximum 280 characters
    • Facebook/Instagram: Up to 63,206 characters
  3. Add Hashtags — Type hashtags in the Hashtags input field. Each platform has a maximum tag limit
  4. Add a Link (optional) — Enter a URL in the Link URL field
    • Check "Add UTM tracking parameters" to automatically append tracking tags
    • Optionally enter a Campaign name for UTM tracking
  5. Add Media (optional) — Click "Select from Media Library" or "Add Image URL"
    • You can add up to 4 images
    • Instagram requires at least one image or video — you cannot create a text-only Instagram post
    • Twitter/X allows a maximum of 4 media attachments
  6. Choose When to Post:
    • Leave the schedule picker empty to save as a Draft
    • Set a future date and time to Schedule the post
    • Click "Publish Now" to publish immediately

Right Column — Preview:

  1. A Platform Preview shows how your post will look on the selected platform (sticky, scrolls with you)

Bottom Actions:

  1. Click "Save Draft" to save without publishing
  2. Click "Schedule Post" if you set a scheduled date
  3. Click "Publish Now" to publish immediately

6.2 Creating a Multi-Platform Post

  1. Navigate to Social PublishingPostsCreate Post
  2. Switch to Multi-Platform mode (toggle at the top)

Main Content (left side):

  1. Select Accounts — Use the MultiPlatformSelector to check multiple accounts (e.g., Facebook Brand Page + Instagram + X account)
  2. Write Base Copy — Enter your main post text in the base copy tab
  3. Customise Per Platform (optional) — Click the platform-specific tabs (Facebook, Instagram, X) to override the base copy for each platform. This is useful when you need shorter text for X or different hashtags for Instagram
  4. Additional Options:
    • Hashtags — Shared across all platforms (or override per platform)
    • Link URL — Shared link with optional UTM tracking
    • Campaign — Select a campaign from the dropdown (if campaigns exist)

Sidebar (right side):

  1. Choose Schedule Type:
    • Immediate — Publish to all selected accounts right now
    • Scheduled — Pick a date and time, all posts go out at the same moment
    • Staggered — Pick a start date/time and a stagger interval (in minutes, 1–1440). Posts go out one by one, spaced by the interval. Example: 3 accounts with 15-minute stagger = posts at 10:00, 10:15, 10:30
  2. Review the Summary card showing: account count, character count, hashtag count, and campaign
  3. Review the Platform Previews for each selected account
  4. Click "Publish Now" (for immediate) or "Schedule X Posts" (for scheduled/staggered)

After Creation:

  1. A success screen shows "Posts Created Successfully" with the count of posts created
  2. Click "Create More" to compose another post, or "View Dashboard" to return to the posts list
  3. All posts in the batch share a post group ID so you can track them together

6.3 Adding Media to Posts

  • Click "Select from Media Library" to choose from previously uploaded images
  • Click "Add Image URL" to enter a direct image URL
  • Images display in a grid (up to 4)
  • Remove an image by clicking its remove button
  • Instagram: At least one image or video is required
  • X (Twitter): Maximum 4 media attachments. Supports images, videos, and GIFs (the system auto-detects the type)

6.4 Adding Hashtags

  • Type hashtags in the Hashtags input field
  • Hashtags appear as badge pills with a # prefix
  • Each platform may have a maximum tag limit
  • Hashtag performance is tracked in analytics (see Section 6.13)
  1. Enter a URL in the Link URL field
  2. Check "Add UTM tracking parameters" to enable tracking
  3. The platform automatically generates UTM parameters:
    • utm_source — the platform name (e.g., facebook, instagram, twitter)
    • utm_medium — "social"
    • utm_campaign — optional, you can enter a custom campaign name
    • utm_content — optional
  4. The tracked URL is stored with the post and used when publishing
  5. You can view UTM performance in the Attribution tab of Analytics

6.6 Scheduling Posts

  1. When creating or editing a post, use the Schedule Picker (calendar + time picker)
  2. Select a future date and time
  3. The post status changes to Scheduled
  4. The publish-social cron job runs every 5 minutes and automatically publishes posts when their scheduled time arrives
  5. Edit lock: Posts cannot be edited within 15 minutes of their scheduled publish time (cancellation is still allowed)

6.7 Managing the Publishing Queue

  1. Go to Social PublishingPosts
  2. Use the List View (default) to see all posts in a table

Filters available:

  • Search box — Search post content
  • Status dropdown — Filter by: All, Published, Scheduled, Draft, Failed, Cancelled
  • Platform dropdown — Filter by: All Platforms, Facebook, Instagram, X (Twitter)
  • Campaign dropdown — Filter by campaign (if campaigns exist)

Table columns:

  • Post — Content preview with hashtags, plus campaign badge if linked
  • Platform — Platform icon and name
  • Status — Status badge (colour-coded). Failed posts show error message. Overdue posts show an "Overdue" badge
  • Date — Published, scheduled, or created date
  • Metrics — Impressions (eye icon), Likes (heart icon), Comments (message icon)
  • Actions menu:
    • View Details — Open full post detail page
    • Edit — Edit draft or scheduled posts
    • Publish Now — Immediately publish a scheduled post
    • Retry — Retry a failed post
    • Delete — Delete the post

Pagination: "Showing X – Y of Z" with Previous/Next buttons.

6.8 Calendar View

Social media posts list
The posts page lists all scheduled, published, and draft posts with platform, status, and date. Switch to calendar view using the toggle at the top.
  1. Go to Social PublishingPosts
  2. Click the Calendar button (next to the List button) to switch views

Calendar Controls:

  • View Toggle: Switch between Month, Week, and Day views (CalendarDays, LayoutGrid, Clock icons)
  • Platform Filter: Filter posts by platform
  • Campaign Filter: Filter by campaign

Calendar Features:

  • Posts appear on their scheduled/published date as coloured dots
  • Colour coding by platform: Facebook (blue), Instagram (pink/red), X (dark)
  • Status dots: Scheduled (blue/primary), Published (green/success), Failed (red/error)
  • Drag and drop — Drag a post to a new date to reschedule it (draft and scheduled posts only; cannot reschedule to a past date)
  • Quick Create — Click on a day to open the Quick Create Modal and create a post directly from the calendar

Legend: A legend at the bottom of the calendar shows the platform colours and status dot meanings.

6.9 Creating Posts from the Calendar

  1. In Calendar view, click on a date
  2. The Quick Create Modal opens
  3. Fill in the post details (platform, copy, media, hashtags)
  4. Set the time for that date
  5. Save — the post appears on the calendar

6.10 Managing Social Campaigns

Social campaigns
The campaigns page lets you group related posts, set goals, and track performance across platforms.

Campaigns let you group related posts together and set performance goals.

Note: Campaign pages under /social/campaigns redirect to Marketing → Campaigns (/marketing/campaigns). Campaign management is centralised in the Marketing module.

Creating a Campaign:

  1. Go to MarketingCampaigns (or click through from Social)
  2. Click Create Campaign
  3. Fill in:
    • Name (required, max 200 characters)
    • Description (optional)
    • Start Date and End Date (optional; end date must be after start date)
    • Goals (optional):
      • Target Impressions
      • Target Engagements
      • Target Clicks
  4. Status defaults to Draft
  5. Click Save

Campaign Statuses:

  • Draft — Not yet active
  • Active — Currently running
  • Paused — Temporarily stopped
  • Completed — Finished
  • Archived — Archived for reference

Status Rules:

  • Archived campaigns can only go back to Draft
  • Completed campaigns can only move to Archived or Active
  • Active campaigns cannot be deleted — pause or archive first

Linking Posts to Campaigns:

  • When creating a post (single or multi-platform), select a campaign from the Campaign dropdown
  • Posts linked to a campaign show a campaign badge in the posts list
  • Campaign detail pages show the most recent 10 posts and total post count

6.11 Viewing Posting History

  1. Go to Social PublishingHistory (/social/history)
  2. This page shows all posts in a simplified table view
  3. Use Search, Status filter, and Platform filter to find specific posts
  4. The table shows: Post content, Platform, Status, Date, Metrics, and Actions
  5. Pagination is available at the bottom

6.12 Viewing Post Details

  1. Click View Details on any post (from the posts list, history, or calendar)
  2. The Post Details page (/social/posts/[id]) shows:

Header:

  • Post title/reference
  • Status badge (colour-coded)
  • Action buttons (vary by status):
    • Draft: "Publish Now"
    • Scheduled: "Cancel Schedule"
    • Failed: "Retry" (with spinner while retrying)
    • Draft/Failed/Cancelled: "Delete"
    • Published: "View on Platform" (external link to the live post)

Left Column — Post Content:

  • Full post text
  • Hashtags as badge pills
  • Link URL
  • Media grid (2-column layout)
  • Details card: Platform, Created date, Published date, Scheduled date, Created By, Platform Post ID

Right Column:

  • Platform Preview (sticky)
  • Performance Metrics (for published posts only):
    • 6 metric boxes: Impressions, Likes, Comments, Shares, Saves, Clicks
    • Engagement Rate (larger box, highlighted)
    • "Last updated" timestamp

6.13 Retrying Failed Posts

  1. Find the failed post in the Posts list (filter by Status → Failed) or on the Post Details page
  2. Check the error message to understand why it failed (e.g., token expired, content rejected by platform, API error)
  3. If the issue is a token expiry, refresh the account token first (see Section 5.5)
  4. Click "Retry" from the action menu or the post detail page
  5. The system will attempt to publish the post again
  6. Maximum 3 retries are allowed (with exponential backoff: 1 second, 5 seconds, 15 seconds between attempts)
  7. After 3 failed retries, the post is permanently marked as Failed and must be cloned or recreated

Cloning a Failed Post:

If retrying is not possible (e.g., content needs to change, or you want to target a different account):

  1. Open the failed post's detail page
  2. Use the Clone action to create a duplicate as a new Draft
  3. Optionally select a different account for the clone
  4. Edit the cloned post as needed and publish

6.14 Social Analytics

Social media analytics
Track engagement metrics, top-performing content, best posting times, and hashtag performance across all connected platforms.

Navigate to Social PublishingAnalytics (/social/analytics).

Three tabs are available:

Performance Tab (default)

Date Range Selector: Quick buttons for 7 days, 14 days, 30 days, 90 days, plus a Refresh button.

Metric Cards (Row 1):

CardIconWhat It Shows
Total ImpressionsEyeHow many times your posts were shown
Total ReachUsersHow many unique people saw your posts
Total EngagementsHeartTotal interactions (likes + comments + shares + saves + clicks)
Avg. Engagement RateMouse PointerAverage engagement rate across all posts

Metric Cards (Row 2):

CardWhat It Shows
Posts PublishedNumber of posts published in the period
Total LikesSum of all likes
Total CommentsSum of all comments
Total ClicksSum of all link clicks

Charts and Tables:

  • Engagement Chart — Line chart showing performance over time (2/3 width)
  • Platform Comparison — Pie chart comparing platforms (1/3 width)
  • Follower Growth Chart — Line chart of follower count over time (full width)
  • Content Type Breakdown — Distribution of content types: image, video, text, link, mixed (1/2 width)
  • Best Times Heatmap — 7×24 grid showing average engagement rate by day of week and hour of day. Helps you identify the best times to post (1/2 width)
  • Top Posts Table — Your best-performing posts ranked by engagement
  • Hashtag Performance — Which hashtags drive the most engagement, impressions, and usage

Export: Click the Export button to download analytics as CSV or JSON. You can specify a date range.

Attribution Tab

Shows how social posts drive website traffic:

  • Total Posts, Total Impressions, Total Clicks, Overall Click Rate
  • Click data broken down by platform
  • Click data broken down by UTM campaign (sorted by clicks)

This tab is useful for understanding which platforms and campaigns are driving the most traffic to your website.

Executive Tab

Permission required: Only users with SOCIAL_EXECUTIVE_READ permission (Admin, Editor) can see this tab.

Filters:

  • Period dropdown: Last 7 days, Last 14 days, Last 30 days, Last 90 days
  • Account dropdown: All Accounts or a specific account

KPI Cards:

  • Total Impressions, Total Engagements, Total Clicks, Posts Published
  • Engagement Rate
  • Per-platform breakdown (Impressions, Engagements, Posts for each connected platform)

Additional Components:

  • Period Comparison Card — Compare current period vs. previous period (e.g., last 30 days vs. the 30 days before that)
  • Top Campaigns Widget — Shows your best-performing campaigns

6.15 Executive Dashboard (Standalone)

A dedicated page is also available at Social PublishingExecutive Dashboard (/social/executive).

This is a standalone version of the Executive tab with:

  • Full KPI grid (Impressions, Engagements, Clicks, Posts Published)
  • Engagement Rate card
  • Platform breakdown cards
  • Period Comparison
  • Top Campaigns
  • Export button for executive reports
  • Same period and account filters

6.16 How Automated Publishing Works

You do not need to take any action for automated publishing. Here is what happens in the background:

  1. Every 5 minutes, the publish-social cron job runs
  2. It finds all posts with status Scheduled where the scheduled time has arrived or passed
  3. It processes up to 10 posts per run
  4. For each post:
    • Checks the account is Connected and the token is not expired
    • If the token is expired, marks the account as expired and the post as failed
    • Sends the post to the platform API (Facebook Graph API, Instagram Graph API, or X API v2)
    • On success: marks the post as Published with the platform's post ID and URL
    • On failure: increments the retry count and marks as Failed (after 3 retries, permanently failed)
  5. In Demo Mode: simulates publishing with fake post IDs and URLs

6.17 How Metrics Sync Works

Engagement metrics update automatically. Here is the schedule:

Post AgeSync Frequency
0–24 hours after publishingEvery hour
1–7 days after publishingOnce per day
After 7 daysNo longer synced (metrics are stable)

What gets synced:

  • Impressions, Reach, Engagements, Likes, Comments, Shares, Saves, Clicks, Video Views
  • Engagement Rate (calculated as: Engagements ÷ Reach × 100)
  • Follower count snapshots (recorded daily for each connected account, used for the Follower Growth chart)

In Demo Mode: The system generates realistic-looking random metrics instead of calling real platform APIs.

6.18 Notifications and Email Dependencies

The social media module does not directly send emails or in-app notifications. However, related modules may notify you about:

  • Campaign status changes — If a campaign linked to social posts changes status, you may receive notifications through the Marketing module
  • Cron failures — The Daily Ops Summary cron (if configured) sends Slack alerts about anomalies including social publishing failures

Social post status changes (published, failed) are visible in the Social Publishing dashboard and Post Details pages.

6.19 Bulk Operations

Bulk Delete:

  • Select multiple posts from the posts list
  • Click the bulk action to delete
  • Only non-published posts can be bulk deleted (max 50 at a time)

Bulk Status Update:

  • Select multiple posts
  • Change status to Draft or Cancelled in bulk
  • Cannot change published or publishing posts

7. Worked Examples

Example 1: Connecting a New Instagram Account and Verifying It Is Ready to Publish

Scenario: Your marketing team just created a new Instagram Business account for a product line. You need to connect it so the team can start scheduling posts.

Steps:

  1. Confirm the Instagram account is set up as a Business or Creator account (not Personal) in the Instagram app settings
  2. Confirm the Instagram account is linked to a Facebook Page (required by Meta's API)
  3. Log in to the Admin Console with an Admin or Editor role
  4. Go to Social Publishing from the sidebar
  5. Click Connect Facebook (Instagram connections come through Meta OAuth)
  6. Log in with the Facebook account that manages the linked Page
  7. Grant all requested permissions (make sure Instagram permissions are included)
  8. Complete the authorisation flow
  9. Back in the Admin Console, verify:
    • The Facebook Page appears with status Connected
    • The Instagram Business account also appears with status Connected
    • The account shows a follower count and profile info
  10. Test it: Create a Draft post selecting the new Instagram account, add an image (required for Instagram), and click Publish Now
  11. Open Instagram and verify the post appears on the account's feed
  12. Back in the Admin Console, the post status should show Published with a "View on Platform" link

Verification Checklist:

  • Instagram account shows as Connected in the accounts list
  • Token expiry date is approximately 60 days from now
  • A test post with an image published successfully
  • The post is visible on the real Instagram account
  • Metrics begin appearing within 1 hour (after the metrics sync cron runs)

Example 2: Creating and Scheduling a Single Post with Image and CTA

Scenario: You want to announce a new article going live next Tuesday at 9 AM, with an eye-catching image and a link to read the article.

Steps:

  1. Go to Social PublishingPostsCreate Post
  2. Select Single Post mode
  3. Choose your Facebook — Brand Page account
  4. In the text area, write your post:
    Our latest deep-dive is live! Explore how independent publishers are
    reshaping digital media. Don't miss the insights from industry leaders.
    Read now and join the conversation.
  5. In Hashtags, add: #IndependentMedia, #Publishing, #DigitalMedia
  6. In Link URL, paste the article URL: https://hyphen.co/articles/reshaping-digital-media
  7. Check "Add UTM tracking parameters"
  8. Enter Campaign name: spring-content-push
  9. Click "Select from Media Library" and choose the article's hero image
  10. In the Schedule Picker, select next Tuesday and set the time to 9:00 AM
  11. Review the Platform Preview on the right — confirm the post looks correct
  12. Click "Schedule Post"
  13. The post now appears in your posts list with status Scheduled and the date "Tue, [date] 9:00 AM"

After Publishing (next Tuesday):

  1. The cron job automatically publishes the post at 9:00 AM (within the 5-minute window)
  2. Check the post in the Admin Console — status should change to Published
  3. Click "View on Platform" to see it live on Facebook
  4. After 1 hour, check the post detail page — engagement metrics (impressions, likes, comments) should begin appearing
  5. In AnalyticsAttribution, you should see clicks attributed to the spring-content-push campaign

Example 3: Creating a Multi-Platform Campaign Post and Checking Results

Scenario: You are launching a "Women in Publishing" campaign and want to post simultaneously across Facebook, Instagram, and X with platform-specific messaging.

Steps:

  1. Create the Campaign first:

    • Go to MarketingCampaignsCreate Campaign
    • Name: "Women in Publishing 2026"
    • Description: "Celebrating women in independent publishing throughout March"
    • Start Date: March 1, 2026
    • End Date: March 31, 2026
    • Goals: 50,000 impressions, 5,000 engagements, 1,000 clicks
    • Status: Active
    • Click Save
  2. Create the Multi-Platform Post:

    • Go to Social PublishingPostsCreate Post
    • Switch to Multi-Platform mode
    • Select all three accounts: Facebook Brand Page, Instagram Business, X account
    • Base Copy:
      Meet the women who are reshaping independent publishing. Our new series
      spotlights their stories, challenges, and triumphs.
    • Click the X (Twitter) tab and override the copy (to fit 280 chars):
      Meet the women reshaping independent publishing. New series spotlights
      their stories and triumphs.
    • Click the Instagram tab and add: Link in bio for the full story. at the end
    • Add hashtags: #WomenInPublishing, #IndependentMedia, #HyphenMag
    • Add Link URL with UTM tracking, campaign name: women-in-publishing-2026
    • Select Campaign: "Women in Publishing 2026" from the dropdown
    • Add the campaign hero image from Media Library
  3. Schedule with Stagger:

    • Choose Staggered schedule type
    • Set start date/time to March 8, 2026 at 8:00 AM
    • Set stagger interval to 30 minutes
    • This means: Facebook at 8:00 AM, Instagram at 8:30 AM, X at 9:00 AM
  4. Click "Schedule 3 Posts"

  5. Success screen shows "Posts Created Successfully — 3 posts created"

Checking Results (after March 8):

  1. Go to Social PublishingPosts and filter by Campaign: "Women in Publishing 2026"
  2. All 3 posts should show status Published with their respective published times
  3. Click into each post to verify:
    • Facebook post has the full copy
    • X post has the shortened copy
    • Instagram post has the "Link in bio" addition and the image
  4. Go to AnalyticsPerformance and select 7-day range
  5. Check the Platform Comparison pie chart to see engagement distribution
  6. Check the Attribution tab to see clicks by platform for the campaign
  7. Go to Executive Dashboard and check the Top Campaigns Widget — "Women in Publishing 2026" should appear with its metrics and goal progress

Example 4: Handling a Failed Post and Retrying It

Scenario: A scheduled post failed to publish. You need to diagnose the issue and get it published.

Steps:

  1. Go to Social PublishingPosts
  2. Filter by Status → Failed
  3. You see a post with a red Failed badge and an error message like: "Account token expired"

Diagnose:

  1. Click View Details to see the full error
  2. The error message says: "Cannot publish — account token has expired"
  3. Note which account the post was assigned to

Fix the Account:

  1. Go to your social accounts list
  2. Find the account — it shows status Expired
  3. Click Refresh on the account
  4. If refresh succeeds, the account returns to Connected
  5. If refresh fails (e.g., token too old), disconnect and reconnect the account through OAuth

Retry the Post:

  1. Go back to the failed post's detail page
  2. Click "Retry"
  3. The button shows a spinner while the system attempts to publish
  4. If successful, the status changes to Published and a "View on Platform" link appears
  5. If it fails again, check the new error message — the retry count is shown (e.g., "Retry 2 of 3")

If All 3 Retries Fail:

  1. The post is permanently marked as Failed
  2. Click Clone to create a duplicate as a new Draft
  3. Optionally choose a different account for the clone
  4. Edit the cloned post if needed
  5. Publish the new post

Example 5: Reviewing Analytics to Identify Top-Performing Content

Scenario: At the end of the month, your marketing lead wants to know which posts performed best and what patterns to repeat.

Steps:

  1. Go to Social PublishingAnalytics

  2. Click the 30 days date range button

  3. Review the summary metric cards for an overview:

    • How many impressions, how much reach, total engagements, average engagement rate
    • How many posts were published, total likes, comments, clicks
  4. Identify Top Posts:

    • Scroll down to the Top Posts Table
    • Posts are ranked by engagement
    • Note what these posts have in common (topic, media type, posting time, hashtags)
  5. Check Best Times to Post:

    • Look at the Best Times Heatmap (7×24 grid)
    • Darker cells = higher average engagement rate at that day/hour
    • Note the best day+hour combinations for future scheduling
  6. Analyse Hashtag Performance:

    • Scroll to the Hashtag Performance section
    • See which hashtags have the highest average engagement rate (not just the most usage)
    • Consider retiring low-performing hashtags and doubling down on high performers
  7. Compare Platforms:

    • Check the Platform Comparison pie chart
    • Identify which platform drives the most engagement
    • Check the Attribution tab to see which platform drives the most clicks to your website
  8. Check Follower Growth:

    • Review the Follower Growth Chart to see trends
    • Correlate growth spikes with specific posts or campaigns
  9. Export the Data:

    • Click the Export button
    • Choose CSV format
    • Select 30-day range
    • Download the file and share with your marketing lead
  10. Executive Summary:

    • Go to the Executive Dashboard (/social/executive)
    • Use the Period Comparison Card to compare this month vs. last month
    • Check the Top Campaigns Widget to see which campaigns hit their goals
    • Click the Export button to generate an executive report

8. Common Mistakes and How to Fix Them

8.1 "I can't connect my Instagram account"

Likely cause: Instagram account is a Personal account, not a Business/Creator account, or it is not linked to a Facebook Page.

Fix:

  1. In the Instagram app, go to Settings → Account → Switch to Professional Account → Choose Business
  2. Link the Instagram account to a Facebook Page via Instagram Settings → Account → Linked Accounts → Facebook
  3. Try the connection flow again through the Meta OAuth flow

8.2 "My scheduled post didn't publish at the right time"

Likely cause: The publish-social cron runs every 5 minutes, so there may be up to a 5-minute delay. If the post is much later or never published:

Check:

  1. Is the post still in Scheduled status? → The cron may not be running. Contact your technical team to verify cron jobs are active
  2. Is the post in Failed status? → Check the error message. Common reasons: token expired, platform rejected the content
  3. Is the account in Expired status? → Refresh the token and retry the post

8.3 "I'm trying to create an Instagram post but it won't save"

Likely cause: Instagram requires at least one image or video. Text-only posts are not allowed on Instagram.

Fix: Add at least one image before saving.

8.4 "My X (Twitter) post was rejected"

Likely causes:

  • Post exceeds 280 characters (including links)
  • More than 4 media attachments
  • Duplicate content (X rejects exact duplicate tweets)

Fix: Shorten your text, reduce media count, or modify the wording slightly.

8.5 "I see 'Account token expired' errors"

Likely cause: Social platform tokens expire periodically:

  • Meta (Facebook/Instagram): ~60 days
  • X (Twitter): Several hours (but auto-refreshes via refresh token)

Fix:

  1. Go to your accounts list
  2. Click Refresh on the expired account
  3. If refresh fails, disconnect and reconnect through OAuth
  4. Then retry any failed posts

8.6 "I can't edit a scheduled post"

Likely cause: Posts are locked for editing 15 minutes before their scheduled publish time.

Fix: You can still Cancel the scheduled post and create a new one with the updated content.

8.7 "I can't delete a campaign"

Likely cause: Active campaigns cannot be deleted.

Fix: First change the campaign status to Paused or Archived, then delete it.

8.8 "Analytics show zero metrics for a published post"

Likely cause: Metrics sync runs hourly. If the post was published less than an hour ago, metrics haven't been fetched yet.

Fix: Wait for the next metrics sync cycle (up to 1 hour). You can also click the Refresh button on the analytics page. If metrics are still zero after several hours, check with your technical team that the sync-social-metrics cron is running correctly.

8.9 "I don't see the Executive tab in Analytics"

Likely cause: Your role does not include the SOCIAL_EXECUTIVE_READ permission.

Fix: Contact your Admin to upgrade your role. Only Admin and Editor roles have Executive Dashboard access by default.

8.10 "I disconnected an account and lost all my posts"

Likely cause: Disconnecting an account with the force option deletes all associated posts.

Prevention: The system warns you if there are scheduled or publishing posts. Always review the warning before confirming.

Recovery: Unfortunately, deleted posts cannot be recovered. Always ensure scheduled posts are moved to a different account or published before disconnecting.


Dependencies & Impact

Social Media Management does not run in isolation — it both consumes content from other modules and feeds data into them.

Upstream (what feeds into Social Media):

  • Editorial — Published articles and workflow submissions can be turned directly into social posts. A SocialPost can carry an articleId (the Strapi article) or a submissionId (the editorial workflow item), so the Share to social action pre-fills the composer with the article link and copy.
  • Marketing — Outreach campaigns can be linked to social campaigns (SocialCampaignOutreachCampaign), letting a single campaign span email/outreach and social channels.

Downstream (what Social Media feeds):

  • Analytics — Engagement data synced into SocialMetrics powers social performance reports, top-content rankings, best-time-to-post insights, and hashtag analysis.
  • Marketing Operations — UTM parameters (utmSource, utmMedium, utmCampaign, utmContent, trackedUrl) on each post let marketing-ops attribute site traffic and conversions back to specific social posts and campaigns.

Impact to be aware of:

  • OAuth tokens are shared infrastructure. If a SocialAccount token expires or is revoked on the platform, every scheduled post for that account will fail until you refresh or reconnect.
  • Disconnecting an account is destructive. Force-disconnecting deletes its SocialPost rows (and their SocialMetrics), which removes those posts from Analytics history.
  • Campaign deletion cascades softly. Deleting a SocialCampaign sets campaignId to null on its posts (the posts survive, but lose their campaign grouping and goal tracking).
  • Cron availability. If the publish-social or sync-social-metrics cron is paused, scheduled posts will not go out and analytics will go stale — these are platform-wide jobs in vercel.json.

Known Limitations

#LimitationImpactWorkaround
1Metrics stop syncing after 7 daysPosts older than 7 days will not have updated metricsThis is by design to reduce API usage. For long-term tracking, export data regularly
2Maximum 3 retries per postAfter 3 failures, a post cannot be retried furtherClone the post and try again with a new post
3X (Twitter) token expiryX tokens expire quickly (hours), requiring frequent refreshThe platform uses refresh tokens automatically, but if both expire, a manual reconnection is needed
4Instagram requires a Business/Creator account linked to a Facebook PageCannot connect personal Instagram accountsConvert to Business account and link to a Facebook Page first
5Instagram text-only posts not supportedAll Instagram posts must include at least one image or videoAlways add media for Instagram posts
6X (Twitter) 280-character limitLong-form content must be significantly shortened for XUse the per-platform copy override in multi-platform mode
7Edit lock 15 minutes before publishCannot make last-minute edits to scheduled postsCancel the scheduled post and create a new one instead
8Campaign management lives in Marketing moduleSocial campaign links redirect to /marketing/campaignsNavigate to Marketing → Campaigns for campaign CRUD
9Maximum 10 posts per cron runIf many posts are scheduled for the same time, some may be delayed by a few minutesThe cron runs every 5 minutes, so backlog clears quickly
10Video publishing to InstagramCarousel (multi-image) publishing is supported, but video processing may have platform-specific delaysCheck Instagram's media status before assuming failure
11No push or email notifications for social post status changesUsers must check the dashboard to see if posts published or failedCheck the Social Publishing dashboard regularly, especially after scheduled posts

FAQ

On this page

1. Feature OverviewHow It Works (Behind the Scenes)Concepts: Account Linking, Posts & Scheduling2. Who Should Use This Feature3. Before You Begin3.1 Platform Credentials (Admin/DevOps Responsibility)3.2 Check Configuration Status3.3 Cron Jobs Must Be Active3.4 Permissions4. Key Terms in Simple Language5. Step-by-Step Setup Guide5.1 Connecting a Facebook Page5.2 Connecting an Instagram Business Account5.3 Connecting an X (Twitter) Account5.4 Understanding Account Connection Status5.5 Refreshing an Account Token5.6 Disconnecting an AccountConfiguration ReferencePlatform connection (OAuth app credentials)Post composer fieldsScheduling fieldsCampaign fields6. Day-to-Day Operations6.1 Creating a Single-Platform Post6.2 Creating a Multi-Platform Post6.3 Adding Media to Posts6.4 Adding Hashtags6.5 Adding Links and UTM Tracking6.6 Scheduling Posts6.7 Managing the Publishing Queue6.8 Calendar View6.9 Creating Posts from the Calendar6.10 Managing Social Campaigns6.11 Viewing Posting History6.12 Viewing Post Details6.13 Retrying Failed Posts6.14 Social AnalyticsPerformance Tab (default)Attribution TabExecutive Tab6.15 Executive Dashboard (Standalone)6.16 How Automated Publishing Works6.17 How Metrics Sync Works6.18 Notifications and Email Dependencies6.19 Bulk Operations7. Worked ExamplesExample 1: Connecting a New Instagram Account and Verifying It Is Ready to PublishExample 2: Creating and Scheduling a Single Post with Image and CTAExample 3: Creating a Multi-Platform Campaign Post and Checking ResultsExample 4: Handling a Failed Post and Retrying ItExample 5: Reviewing Analytics to Identify Top-Performing Content8. Common Mistakes and How to Fix Them8.1 "I can't connect my Instagram account"8.2 "My scheduled post didn't publish at the right time"8.3 "I'm trying to create an Instagram post but it won't save"8.4 "My X (Twitter) post was rejected"8.5 "I see 'Account token expired' errors"8.6 "I can't edit a scheduled post"8.7 "I can't delete a campaign"8.8 "Analytics show zero metrics for a published post"8.9 "I don't see the Executive tab in Analytics"8.10 "I disconnected an account and lost all my posts"Dependencies & ImpactKnown LimitationsFAQ