DEV Community

Meredith Hassett
Meredith Hassett

Posted on

Working with the Patreon API (now that we know what's going on)

OK so now that we know what is going on with Patreon API, we're ready to start working with! I created an example site where I lead hikes and to access Hike photos, you'll need to subscribe to a Patreon reward tier. While this is just an example, I am using it to help my musical friends rebuild their teaching practice and include extra opportunities to contribute to get access to more music. Stay tuned to see the result of her site!

Patreon and Wix side by side

For now, let's build our website on Corvid by Wix so we don't have to worrying about setup and hosting for our site. I set up a basic UI to handle where we'll put our tiers of Rewards. With Corvid and Wix, we can added a repeated element (called a repeater) that has built in functionality to iterate through all items in a data list to help us customize display of the data more easily. I'll add one of those to my page as well.

Once the UI is ready to go, we need to fetch the tiers from Patreon. If we dynamically grab the data from Patreon, this reduces are maintenance costs down the line as any time we add new levels or update what a level costs or provides, we will see those updates on our site.

Using Corvid, I am going to switch over to my backend code for my website and add a new JavaScript Module. This module will be called pateron.jsw as it will house any and all interactions we need with the Patreon API. As I mentioned in my above linked blog post, the npm module may not work for you as it does have hard coded functionality inside.

Adding a new JSW to the backend

In this example, we have access to the data we need via the npm helper module, so I am going to work with it.

New npm module link

To install an npm module with Corvid, all you need to do is use the GUI to search for and install the package.

Search and install new npm package

Once we have the module installed, back in our web module code, we need to import the Patreon API from the module. Since the default export is not set for the Patreon npm module, we do need to define the export we are looking to import. So at the top of our code, let's import the patreon export from Patreon. I gave it an alias so I more clearly remember which functionality I am working with, but it's ok if you don't.

import { patreon as patreonAPI } from 'patreon'
Enter fullscreen mode Exit fullscreen mode

Next I am going to create an export function as we need to be able to access this from the UI. Make sure to give it a descriptive name of the functionality it provides.

export async function getRewardTiers() {

}
Enter fullscreen mode Exit fullscreen mode

Now we need to initialize a new Patreon client in this function. Since this is a static site for myself (or your client), I can use my Creator's Access Token that I get when I create a new client in the Patreon Portal. If you haven't created a client, make sure to do so now.

Patreon Portal with Client created

We can pass this Creator's Access Token to the Patreon API to create a new client. I created a constant to hold this access token value for security purposes. To use the secrets manager from Wix, check out some of my other blog posts.

const patreonAPIClient = patreonAPI(creator_access_token)
Enter fullscreen mode Exit fullscreen mode

With our new client initialized, we can access our creator data using the /current_user or /current_user/campaigns endpoint. As a reminder, the /campaigns/${id} endpoint does not work with the npm modules as noted in the linked blog post at the top of this one. I am going to access the current user's campaigns as this also holds reward tier information.

patreonAPIClient('/current_user/campaigns')
Enter fullscreen mode Exit fullscreen mode

The Patreon API Client is asynchronous, so we need to handle when this promise returns. We can grab the store object when the promise returns.

patreonAPIClient('/current_user/campaigns')
    .then(({ store }) => {
    })
Enter fullscreen mode Exit fullscreen mode

This store object contains 3 things: user, campaigns, and rewards. I am only interested in the Rewards for this example, so I am going to parse out the rewards.

const rewards = store.findAll('reward').map(reward => reward.serialize()
Enter fullscreen mode Exit fullscreen mode

However, beyond just wanting all the rewards, I only want rewards clients can contribute to, so I want to filter out those with a URL value set. To do this, we have to traverse the object structure to get to the Attributes of a reward, which is where the url property, if set, lives. Once we are in the attributes object, we want to filter on if url is not null. Additionally, we really only need the attributes object of a reward to get all relevant info, so I am only going to return the attributes object for each reward.

let rewards = store.findAll('reward').map(reward => reward.serialize().data.attributes).filter(reward => reward.url)
Enter fullscreen mode Exit fullscreen mode

Once we have the reward's attributes object as an array of rewards, we have one last step before we can return this array. Repeaters in Corvid take an array of objects that contain an "_id" property with a value of string. So we need to append this ID to each of our objects. Let's loop through each object in the array of rewards and add the "_id" property.

for(let i = 0; i < rewards.length; i++){
    rewards[i]._id = `00${i}`
}
Enter fullscreen mode Exit fullscreen mode

Now our array of Rewards objects is ready to be returned from our promise. Make sure to return rewards.

return rewards
Enter fullscreen mode Exit fullscreen mode

And lastly, make sure this function that we just built has a return to make sure the rewards data reaches the calling code.

export async function getRewardTiers() {
    const patreonAPIClient = patreonAPI(access_token)
    return patreonAPIClient('/current_user/campaigns')
        .then(({ store }) => {
            let rewards = store.findAll('reward').map(reward => reward.serialize().data.attributes).filter(reward => reward.url)
            for(let i = 0; i < rewards.length; i++){
                rewards[i]._id = `00${i}`
            }
            return rewards
        })
}
Enter fullscreen mode Exit fullscreen mode

Great! Now we can work with the Rewards data on our UI. Switch back to your page where you want to show the reward tiers.

Photos page with repeater and IDE

The first thing we need to do on the UI code is import the backend function to get the reward data. To do this, we use the standard import notation and traverse to our backend code files.

import { getRewardTiers } from 'backend/patreon.jsw'
Enter fullscreen mode Exit fullscreen mode

Now we can work with the exported getRewardTiers function. In our page's onReady function, define a new variable that we can use to set and update the page's data.

let data
Enter fullscreen mode Exit fullscreen mode

Next, call our getRewardTiers function, and in the promise return, set the response to the data variable.

getRewardTiers().then((result) => {
    data = result
}
Enter fullscreen mode Exit fullscreen mode

Corvid exposes APIs to work with different Wix components, like the repeater we have the page. Looking at the Wix Repeater API, we see that we can use the data property to get and set values for the repeater. We can then go ahead and set the value of our data variable to the data property of the repeater.

$w('#patreonRepeater').data = data
Enter fullscreen mode Exit fullscreen mode

Once the data is set, we can iterate through each item in the repeater using the Repeater API's forEachItem function. This will enable use to iterate through not only the data bound to each item in the repeater, but also access each UI element in the repeater for a specific item. This lets us update the context of only the selected data element in an array of data and UI elements, instead of updating the global UI element. In the function callback handler, we pass in the parameters $item and itemData. These allow us to work with only the select UI element for that object in the array and the specific data for that index in the object array. Instead of having to access everything at index i, we can access it it with $item or itemData.

$w('#patreonRepeater').forEachItem(($item, itemData) =>{
    $item('#rewardTitle').text = itemData.title
    $item('#rewardDescription').text = "To receive this reward, the monthly pledge is $"+ itemData.patron_amount_cents/100
    $item('#rewardLink').link = "https://www.patreon.com"+itemData.url
})
Enter fullscreen mode Exit fullscreen mode

When we preview our page (aka go to QA), we can see a list of Patreon Reward tiers for our site. When we click the link, we'll automatically be taken to the pledge page for the tier where the user can enter their credit card information and start their pledge.

Wix page with checkout

This is a great opportunity for creators to create a centralized landing page where all of their support levels are available to any and all of their clients!

Top comments (0)