Building a Post Scheduler for Facebook Pages with Node.js and React

In this tutorial, we are building a Post Scheduler for Facebook pages. We’ll start off by creating an Express.js web server and use Passport.js to authenticate users with Facebook. After setting up authentication, we’ll build a react app to provide users with an interface to schedule text and images posts for Facebook pages.

Getting Started

Let’s start by initializing a package.json file by running npm init in your working directory and add these dependencies.

Run  npm install. Now create a  server.js in your working directory and add this code. We’re using EJS templating engine and mongoose ODM for the querying database.

We need to set up an HTTPS server for our app to use Facebook Graph API. We’re creating an Express.js app and passing it to https.createServer along with our self-signed certs. You can generate self-signed SSL certificate by running

Also, add your certs directory to the  .gitignore file. We’re using session-file-store module to persist user sessions by storing them on the file system. We’re using config module to retrieve config. In index route, we’re rendering app.ejs view which will bootstrap CSS and Javascript and mount React app.

App Configuration

We’re using config module to store and retrieve data from a separate config file. Create default.json file inside config directory.

Add your Facebook app id and secret along with a strong secret to secure express sessions.  Also, add this file to .gitignore.

User and Schedule Posts Schema

We’ll store users in MongoDB users collection after authentication. Let’s define User and Post schema and models. Create  database/Schema.js file in your working directory and add this code.

Now create  UserSchema.js and  PostSchema.js file.

Passport Facebook Authentication

We’re using Passport’s Facebook strategy to authenticate users and retrieve an access token. Let’s define a passport Facebook strategy. Create auth folder in your working directory and create passport.js file in it.

Now add it to your login route middlewares. Create routes/login.js file and add this code.

We’re asking users for permissions to allow access to manage their Facebook pages. Users will be redirected back to our callback URL after authorization and their profile along with access token will be passed to passport strategy callback. Add these routes to your app in  server.js.

In passport strategy callback, we’re querying the collection with mongoose findOneAndUpdate method. If a user already exists with facebookID, we’ll update it. Otherwise, we’ll create a new user. After create or update, user profile will be passed to passport’s callback to create a session.

Post Scheduler

Now that we’ve set up authentication, we can start building our post scheduler.  Add app.ejs view to views folder and add this code to it.

If a user is authenticated, we’ll render #root  div on which we’ll mount our React app. Otherwise, we’ll render a link to the login page. Add login.ejs view to views folder.

Here’s what it looks like.

After authentication, user will be redirected back the callback URL and a session will be created. We’ll render our React app if user is authenticated. Let’s create our App component. We’ll place our frontend code in src folder. Create src/app.js file and add this code.

App component is rendering a Scheduler and Posts component. In Scheduler component, we’ll render a form to input details for scheduling and Posts component to render scheduled posts.

In Scheduler component, we’re rendering a textarea for text input, a file input to upload an image, a drop-down with a list of pages and a DateTime picker to select date and time. This is how it looks like.

Add state and callbacks to handle onChange events in our Scheduler component.

On file input change, we’ll validate it by mime type. To validate date add these methods.

To retrieve user pages, we’ll requests /pages route.

To handle this request, add this route your routes/scheduler.js  file.

We’re using fb node module to communicate with Facebook Graph API. Currently, Facebook Javascript SDK doesn’t support Node.js. After retrieving pages, we will return an array of page id and names as response and update pages state in Scheduler component.

To handle form submit, add this method.

On form submit, we’ll validate inputs. User can schedule a post with message or photo. One of these is required otherwise we’ll show an error. After validating all fields, we’ll pass data to /schedule route with axios post method. Add a  /schedule endpoint route handler to routes/scheduler.js file.

We’re using express-fileupload middleware to handle file uploads. If a file is present, we’ll move it to media directory. We’ll generate a random string and concatenate to file extension to create a unique name for the uploaded file. After moving uploaded file, we’ll create a new document in posts collection and return scheduled post as response. we’ll then call  addToScheduledPosts props method and pass it post to add scheduled posts. This is how our scheduler form looks like.

Scheduled Posts

Update App component constructor and add state.

We’ll pass posts state down to our Posts component along with delete and publish methods as a callback for onClick events.

On the component mount, we’ll retrieve user’s scheduled post and pass them to Posts component. Add these route handlers to routes/scheduler.js.

On request to /posts route, we’ll return all scheduled posts with where user_id matches with requests user.id  and published  is set to false.

On requests to /posts delete request, we’ll use mongoose findByIdAndRemove method and remove the photo from media directory if its type is photo.

On requests to /schedule/publish route, we’ll use post.user_id  to retrieve page access token. we’ll dynamically generate requests params. If it’s photo post, we’ll use fs.createReadStream method to open a read stream and use it to publish photo post to /page-id/photos Graph API endpoint. On successful publish, we’ll update post document with posts_id and mark it as published.

Update App component’s render method and pass these methods as props.

Create Posts component and add this code to display schedule post.

We’re binding deletePost and publish  prop methods to Delete and Publish button onClick handlers. When clicked, they’ll call delete and publish method on App component with an id of the post. We’ve already defined route handlers to handle those requests. We’ll remove published or deleted posted from scheduled posts after a success response from the server. This is how our scheduler form and posts look like.

Cron Scheduler

So far we’ve been manually publishing scheduled posts by clicking on publish button. Now we’ll use cron task scheduler to publish pending posts. Add cron/scheduler.js file to your project.

CronJob will execute callback every second to check if there’s a post pending for publishing in our posts collection. Since we’re storing schedule_time in seconds on post collection, we can query our collection by comparing current time to schedule_time.

For every selected post, we’ll retrieve page token with its  user_id and then publish to the page by calling publishPost.

I’ve set up a GitHub repository for you guys. Build instructions are available in the readme file. If you’ve any issue, please comment and I’ll try to help you.

Share this post

8 thoughts on “Building a Post Scheduler for Facebook Pages with Node.js and React”

  1. I have a question. Can I add the option to publish a photo in my personal account profile registered on facebook?. How could I achieve or add that option?. Thnk!

    1. To publish to a user profile, we need publish_actions permission which was deprecated. Apps created after 24 April 2018 won’t be able to publish to user profiles. The only way you can share to user profiles is using Facebook’s Share dialogs.

  2. Good job. Please, I am interested in developing an app that displays the number of likes of our facebook page. Any hint?

  3. Thanks for the article and code example!

    I am trying to get your example working on a localhost setup. I have MongoDB, and the SSL working, and this is what my config looks like:
    {
    “appId”: “xxxxxxxxxxxxxxxxxxx”,
    “appSecret”: “xxxxxxxxxxxxxxxx”,
    “sessionSecret”: “EXPRESS_SESSION_SECRET”,
    “callbackURL”: “https://localhost:8888/auth/facebook/callback”,
    “scheduler_timezone”: “Asia/Karachi”
    }

    On my facebook developer console, under “App Domains” I have “localhost”. Then at the bottom of the page under website, I have my site URL as https://localhost:8888

    Finally, under “Client O Auth Settings” I have my Valid OAuth Redirect URIs set to https://localhost:8888/auth/facebook/callback

    With all that being said I still get this error:
    “Can’t Load URL: The domain of this URL isn’t included in the app’s domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings.”

    Any ideas as to how to fix this? In your example it looked like you ran it on a live server, have you been able to get this running on a localhost? I’d appreciate any help you are willing to give.

    Thanks!

  4. Can I use mongoose Schema without a database? I am building a microservice for facebook authentication. How can I pass accessToken in done.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.