Content Sharing System

by Givey Team

16 December 2015

We have always been transparent at Givey when it comes to the business side of things. So we thought why not be transparent about our technology?

There is a lot going on behind the scenes on Givey, but where better to start than our unique content system.

You will no doubt be aware that you can now choose images from your Facebook or Instagram account to serve as content for donations, so let’s take a look at the process.

Content Sharing System

Originally, we wanted to incorporate the Facebook login dialog. It is a much better experience for our users since it allows you to remain on Givey while logging in. However, we also had to consider how users would use Instagram. Instagram doesn’t have the same popup that Facebook provides so, in an effort to make things simpler for both ourselves and our users, we decided to use the redirect method.

So, when you click either the Facebook or Instagram button, you are taken to the respective website in order to confirm the request for permissions. Once you accept the permissions, you are redirected back to Givey with a code in the URL. We use this code to get an access token for you. The problem with this code parameter is that you cannot rename it. Instagram and Facebook both use the parameter name of “code”. So, in order to differentiate the code, we add the “provider” parameter.

Now that we have these parameters, we can get your photos. The problem we came across though is that you just land on the same page and have to click the button again. So, with a little help from Javascript, we auto click the relevant button.

This button triggers a method which loads the relevant module. We have several modules for each of the main providers we support. These modules all have the same methods (“authorize_api”, “channel_resources”, “single_resource”). Before we load your images, we need to obtain an access token for you. That’s where the code comes in. We send that to the module and trigger the “channel_resources” method. This method needs to call the “authorize_api” method in order to get the access token. So, we send the code to Facebook and they return an access token for us to use. With this access token, we create an identity for you in our database (or update it if it already exists).

For Facebook, we use the Koala gem to send requests to the Facebook API. This makes it easy for us to get things like access tokens and retrieve information about you.

Instagram is a bit simpler. All we need to do is send a normal HTTP request to the instagram API with the access token. Once we retrieve your photos, we display them in a modal for you to choose from.

We knew we needed some sort of pagination, so we decided to go with the classic page 1, page 2 etc method. This worked well for Facebook. The API response provides a token which can be used to access the next page of results or the previous page of results. Instagram do things a bit differently however. Their site is built using an infinite scrolling pagination system. Their API also follows the same technique. They do provide a next page token in the form of the last ID of the last photo, but they have no way to get the previous page. We had to decide whether we were going to “monkey patch” a previous page link, or use the infinite scrolling option. We decided on the latter as it made much more sense than writing code just to make one provider work when they would all work with the infinite scroll option.

Once you have decided on which of your photos you would like to share, we send that request off to the server. This invokes the next module method “single_resource”. We again need to authenticate this request, but as you will recall, we stored the access token in our database. So we call the same “authorize_api” method. This method checks to see if there is a “code” parameter passed to it. If not, it uses the “user_id” parameter to grab the Identity we created/updated and use its token to get the resource.

After the API returns the information, we copy the photo and upload it to Cloudinary, which is our image storage provider. We need to copy the photo so that we can avoid issues with display properties and permissions on the photo. When you chose the photo, you gave us permission to view it but this isn’t the case for a normal user viewing your photo on Givey. They would need to have permission to see it.

And that’s how the image upload portion of the new content system works.

The URL box is a different matter. When you enter a URL we first need to parse it. We detect the host of the URL and check to see if we have a provider module for it. These modules are all specific to the provider and all contain their own methods of getting information about the content, while maintaining the class structure (“authorize_api”, “channel_resources”, “single_resource”).

If we don’t have a module for the URL (ie: you have chosen to share your blog) then we need to get the information ourselves. We do this by scraping the web page and grabbing its meta data. We use a gem called Nokogiri which allows us to make a request to the web page and parse the HTML elements.

This posed a problem since not all websites contain all the meta data we need and some contain other forms of meta data (WordPress). So, in an attempt to get as much information as we can, we check for several different types of meta data.

The information we are looking for is the title, description and an image. We first attempt to look for Facebook meta data.

<meta name="og:title" content="" />
<meta name="og:description" content="" />
<meta name="og:image" content="" />

If we can’t grab any of that, we look for WordPress meta data.

<meta property="sailthru.title" content=""  />
<meta property="sailthru.description" content=""  />
<meta property="sailthru.image.full" content=""  />

We eventually default to the normal meta data.

<title></title>
<meta name="description" content="" />

If we do find an image, we need to verify it is a valid image. We do this by sending a request to the URL of the image and verify the HTTP status.

Regardless of the method chosen to upload content, everything else is the same after we have all the information we need.

By Carl Markham

Comments are closed.