Fetch WordPress.com Post to Salesforce (via wordpress.com api)

As you may have noticed, this site is hosted on wordpress.com and I have thinking about what could I do with the Rest API provided by wordpress.com and the Salesforce platform (what else?). I had a few ideas in mind, however, I wanted to build something simple that would show building an integration to an external service. After discovering that posts can be pulled through the API without authentication, I decided to built a post subscription service that would notified users via a chatter group when new posts have been added to a wordpress.com site.

Let’s get started!

The WordPress.com API

WordPress.com public api endpoint is https://public-api.wordpress.com/rest/v1.1/. The resource to fetch posts of a specific site is /sites/$site/posts via a http GET method. You would replace $site with with either the domain or the site id. For example to fetch all posts published in this blog you would send a request with the following endpoint.

https://public-api.wordpress.com/rest/v1.1/sites/terencechiu.com/posts

Clicking the above link will actually display the json response with my post data included. Now that we know how to pull post data from my blog the next step is how to pull the data into a Salesforce org.

Building the integration in Salesforce

Here is a list of items to build:

  • A custom setting to store wordpress.com domain.
  • A custom object to store post data
  • Apex class to handle callout to the API endpoint, batch class to facilitate the callout and updating records, and a schedulable class so that the fetch can occur on daily basis.

Custom Setting to store domain

Instead of hardcoding domain names in the Apex class I created a custom setting to store domain url and also a last fetch date field that we can use to track when we last pulled for new posts. Last fetch date will be used in the callout where we will use a filter so that we do not pull posts that we already fetched already.

Custom Object

To store the title and url of the post I created a custom object called WP Post. It has two custom field to store the post data.

Apex Classes

Handling the Callout

Our web service callout method will accept two arguments.

  • domain : The domain of the wordpress.com site.
  • lastFetchDate : The date when posts from the blog site was last polled.

The above parameters will be pulled from the custom setting we created.

public static String postRetrievalCallout(String domain, Date lastFetchDate){
String respBody;
String dateFilter = lastFetchDate != null ? '?after=' + lastFetchDate.year() + '-' + lastFetchDate.month() + '-' + lastFetchDate.day() : '';
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint('https://public-api.wordpress.com/rest/v1.1/sites/' + domain + '/posts/' + dateFilter);

try{
HttpResponse resp = h.send(req);
respBody = resp.getStatusCode() == 200 ? resp.getBody() : 'Error during callout: ' + resp.getStatusCode() + ': ' + resp.getStatus() + ' - ' + resp.getBody();
}catch(Exception ex){
respBody = 'Error during callout: ' + ex.getMessage();
}

return respBody;
}

We instantiate an httprequest object and set the method to GET and the public api endpoint. Using the last fetch date value we add a query parameter to the request to only fetch posts that were created after the previous fetch date. We send the request via send method of the Http class and we return the response from callout in string format.

Processing the response

The next step is to parse the response in json format and extract the following information.

  • Title of the post
  • Link to the post

We will accomplish the parsing with the below apex method. It takes the response string and uses it to create a JSON parser object.

public static List parsePostResp(String respBody){
List posts = new List();</b></i>

JSONParser parser = JSON.createParser(respBody);
Boolean titleFound = false;
Boolean urlFound = false;
WP_Post__c post;

while(parser.nextToken() != null){
if(parser.getCurrentToken() == JSONToken.FIELD_NAME &amp;&amp; parser.getText() == 'title'){
parser.nextToken();

titleFound = true;
post = new WP_Post__c();
post.Title__c = parser.getText();
}
else if(parser.getCurrentToken() == JSONToken.FIELD_NAME &amp;&amp; parser.getText() == 'short_URL'){
parser.nextToken();
titleFound = false;
post.URL__c = parser.getText();
posts.add(post);
}
}

return posts;
}

Iterating through each json token in the parser we will identify the title and url tokens and pull the text values. Each title and url pair results in a new WP Post object which will be added to a list of WP Posts. The method ultimately returns the list of WP Post objects.

Scheduling Post Sync

To fetch new posts on a scheduled basis I created a Schedulable class that executes a Batchable class. A query to select all WP Sites custom setting records will be run when the batch job executes.

global class ScheduleWPPostFetch implements Schedulable {

 global void execute(SchedulableContext sc) {

 WPPostFetchBatch wpBatch = new WPPostFetchBatch();

 wpBatch.query = 'SELECT Domain__c, Last_Fetch_Date__c FROM WP_Sites__c';

 Database.executebatch(wpBatch, 5);

 }

}

The batch class

The batch class will loop through all WP site records found in the query and pass the domain and last fetch date of each record as arguments when calling the WPPostSubscribeService.postRetrievalCallout method. Any WP posts returned from the method execution will be stored in the posts list variable. Note that in order to perform web service callouts the batch class needs to implement Database.AllowsCallouts.

global class WPPostFetchBatch implements Database.Batchable, Database.AllowsCallouts{</b></i>

global String query;

global Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List scope){
List posts = new List();
List upsRecs = new List();

for(sObject wpSite : scope){
String httpRespBody =WPPostSubscribeService.postRetrievalCallout ((String)wpSite.get('Domain__c'), (Date) wpSite.get('Last_Fetch_Date__c'));
if(!httpRespBody.contains('Error during callout:')){
posts.addAll(WPPostSubscribeService.parsePostResp(httpRespBody));
wpSite.put('Last_Fetch_Date__c', Date.today());
upsRecs.add(wpSite);
}
}

try{
insert posts;
update upsRecs;
}catch(DMLException ex){
system.debug('Error during post insert: ' + ex.getMessage());
}

}

global void finish(Database.BatchableContext BC){
}
}

Each individual WP Site record’s Last Fetch Date field will also be updated with the current date as long as the web service callout was successful. Any new posts generated from response parsing will be inserted as new WP Post records.

Alerting Users of New Posts

I set up a Chatter group that will be used send out notifications to members of the group each time a new post has been created. Naturally, I went with Process Builder to achieve this task.

I created a process builder flow against the WP Post object. The process runs only when a record is created.

The action group has no additional condition and just executes the action since we want to post to the group each time a new WP Post record is created.

Our only immediate action is to post to the Chatter group with a message that includes the Title field value and he URL field value from the WP Post record (which would have been populated during the fetch job).

Here is a screen shot of what the group posts would look like.

There you have it. If you ever want to subscribe to a wordpress.com blog or create a backup of your wordpress.com blog in a Salesforce org I hope this blog post can help you get started. All code covered in the post can found in this Github repo.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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