Integrating a Medium RSS Feed into a Website

Riley Entertainment Web Dev
4 min readAug 23, 2021

Like most blog / journal / content management platforms, Medium provides an RSS Feed for your stories. RSS stands for Really Simple Syndication, and is used across the web to give readers an easy way of subscribing to blogs or newsfeeds. Mozilla Thunderbird is the RSS Reader software I use. An RSS Feed is really just an XML document that follows a particular specification.

TL;DR Version

If you’re not looking for all the excrutiating details:

  1. Trying to read the Medium RSS Feed directly from JavaScript will end in CORS and authorization issues.
  2. Create an API on your web server that reads the feed instead, and call that from JavaScript.

This article will detail how to build a simple API to read RSS feeds using PHP.

Fetching an RSS Feed Using JavaScript (Watch out for CORS!)

Since RSS is just XML, it seems like it should be easy enough to load a feed in JavaScript using the Fetch API. But not so fast… Unless the web server hosting the feed is set up to allow access from anywhere, which is a security risk, you’re going to run into a CORS error.

Medium is all like, *I* control *you*, bro.

CORS stands for Cross-Origin Resource Sharing. I came across a decent article by David Katz here on Medium discussing the options to deal with this issue. In short, the best approach is to retrieve the RSS Feed from your web server, rather than trying to retrieve it from the client’s browser.

Fetching an RSS Feed Using PHP

Since PHP is what’s available to me on my website’s hosting provider, I’ll be showing how to retrieve an RSS Feed using PHP. While it’s typical for PHP-based web pages to mix HTML and PHP in the same file, my preference is to keep them separate. PHP code gets run on the server, while HTML and JavaScript are interpreted and run on the client’s browser — so I find that this separation keeps things more clean. While I have yet to play around with automated testing for PHP, I suspect this approach will help your code be more easily testable.

For my particular use case, I’m only looking to retrieve the title, URL, and publish date for all my blog posts. I’ll use that information to display a panel on the home page like so:

Side panel with links to the latest blog posts

PHP provides the following core functionality that we’ll make use of to achieve this:

  1. The file_get_contents function makes it easy to load the contents of an external web page into a string.
  2. The SimpleXML library can be used to parse the XML of the RSS Feed.
  3. The JSON library provides a json_encode function that converts basic data types into JSON, which is my preferred data format for API calls.
  4. The date / time library provides full support for parsing, manipulating, and formatting dates and time zones. For my use case, I wanted to ensure I was showing the publish date in my own time zone (CST).

This is actually the first time I’m coding in PHP. A few things I’ve noticed that might be confusing for others new to PHP:

  1. Arrays are actually ordered maps, and can be treated as either regular indexed arrays or dictionaries. I used arrays exclusively to build the API response, coupled with the json_encode function.
  2. Namespaces mostly work as I expected, with the exception that when you are inside the scope of a namespace, you must prefix any global symbols with the backslash character.

I’ve organized my source code as follows:

/source/php
RileySiteUtils.php
RssUtils.php
/public_html
index.html
/api
/blog
get_webdev_blog.php
/javascript
RileySiteUtils.js
RssFeedPanelManager.js

The two files in the /source/php folder are outside of the website’s public space to ensure they’re not directly accessible through the browser.

Here’s the source code for the PHP files. I think this provides a decent working example for anyone looking to do something similar.

RileySiteUtils.php:

<?php
namespace Riley;
const SITE_TIMEZONE = "America/Winnipeg";
?>

RssUtils.php:

<?php
namespace Riley\RssUtils;
include_once "RileySiteUtils.php";function convertRssItemToSummary(&$rssItem) {
$originalTimestamp = \DateTime::createFromFormat(\DateTime::RFC2822, (string)$rssItem->pubDate);
$translatedTimestamp = $originalTimestamp->setTimezone(new \DateTimeZone(\Riley\SITE_TIMEZONE));

$isoDateTime = $translatedTimestamp->format("Y-m-d") . "T" . $translatedTimestamp->format("H:i:s");

$result = array(
"title" => (string)$rssItem->title,
"url" => (string)$rssItem->link,
"publishDateTime" => $isoDateTime,
);

return $result;
}
function convertRssItemToSummaryList(&$rssItemList) {
$result = array();
foreach($rssItemList as $rssItem) {
array_push($result, convertRssItemToSummary($rssItem));
}
return $result;
}
function convertRssChannelToSummary($url, &$rssChannel) {
$result = array(
"title" => (string)$rssChannel->title,
"blogUrl" => (string)$rssChannel->link,
"feedUrl" => $url,
"itemList" => convertRssItemToSummaryList($rssChannel->item),
);
return $result;
}
function loadRssFeedSummary($url) {
$result = false;

$fileContents = false;
try {
$fileContents = file_get_contents($url);
} catch ( Exception $e ) {
}

$xmlResponse = false;
if ( $fileContents !== false ) {
$xmlResponse = new \SimpleXmlElement($fileContents);
}

if ( $xmlResponse !== false ) {
$result = convertRssChannelToSummary($url, $xmlResponse->channel);
}
return $result;
}
?>

get_webdev_blog.php:

<?phpinclude "../../../source/php/RssUtils.php";error_reporting(E_ALL ^ E_WARNING);$blogEntryArray = Riley\RssUtils\loadRssFeedSummary("https://medium.com/feed/@webdev_59507");if ( $blogEntryArray === false ) {
http_response_code(404);
} else {
header("Content-Type: application/json");
echo json_encode($blogEntryArray);
}
?>

You can look at the source code on the Riley Entertainment website for index.html and the two client-side JavaScript files.

I decided to try my hands at coding client-side JavaScript modules for the first time. This was something we hadn’t done yet at the time I left my last job, as we had only fairly recently dropped support for Internet Explorer. I’m curious how well supported JavaScript modules are across different browsers and platforms. I plan to discuss this in my next post…

--

--

Riley Entertainment Web Dev
0 Followers

Indie Game Dev and Content Creator, sole proprietor of Riley Entertainment