Publishing Guru Cards to a Third-Party
This article shows you how to use Guru's SDK to publish cards from Guru to a third-party. We'll use an Intercom Help Center as the platform we're publishing to as an example.
If you'd like to jump right to our code, the entire script to publish to Intercom is available here. We also have examples that publish to Readme and Salesforce.
What we'll cover here
- Understanding the nomenclature
- Running the script
- The Publisher class
- Creating and updating Intercom articles
- Finding Intercom Collections and Sections
- How the script stores data
- Publishing to other third-party platforms
Understanding the nomenclature
Our SDK refers to objects by their Guru names (cards, boards, etc.) and refers to the third-party as being "external". So when we say we'll publish a Guru Card to become an Intercom Article, the SDK refers to the Intercom Article as an "external card".
Intercom also has grouping structures called collections and sections. We can match Guru objects up to these structures. Here's an example:
Guru Name | SDK Generic Name | Intercom Name |
---|---|---|
Collection | external collection | Collection |
Folder | external section | Section |
Card | external card | Article |
Running the script
To run the script you'll need to set up a few environment variables:
GURU_USER
is your Guru username (email address).GURU_API_TOKEN
is your Guru API token.INTERCOM_API_TOKEN
is your Intercom API token.
Once you have those values you can run the intercom_publish.py
script:
GURU_USER="[email protected]" GURU_API_TOKEN="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" \
INTERCOM_API_TOKEN="dG9rOjEyMzRhYmNkLTU2NzgtYWJjZC1kZWZhLTEyMzQ1Njc4MTIzNDp2MS4wMA==" \
python intercom_publish.py
The Publisher
class
Publisher
classGuru's SDK provides a base Publisher
class. This implements all the functionality you need on the Guru side. Here's what it does for you:
- Enumerates the Board Groups, Boards, Sections, and Cards in a Collection.
- Tracks object versions so it knows when a Card has changed and needs to be published.
- Remembers the external ID of each object.
- Knows whether an object has been published before, so it knows when to create vs. update the external object.
- Finds links between Guru Cards and helps you convert them to be links between external articles.
To publish Cards to Intercom, we extend The SDK's Publisher
class to create an IntercomPublisher
class. The IntercomPublisher
class is where we implement what's specific to Intercom, like the API calls to create and update Intercom articles.
To publish some content, we just need to tell it where to start. Here's an example:
import guru
g = guru.Guru()
publisher = IntercomPublisher(g)
publisher.publish_collection("Help Center")
That tells the SDK to enumerate all of the boards, sections, and cards in your Help Center collection and see which objects have changes that need to be published. When it finds an object that needs to be created or updated in Intercom, it'll call the method to make that update -- since these methods are Intercom-specific, they're the ones we'll have to implement in the IntercomPublisher
class.
Creating and updating Intercom articles
When a Card needs to be published, one of two methods will be called:
create_external_card
is called when the Card has never been published before and needs to be created in Intercom.update_external_card
is called when the Card has been published before and we need to update the Intercom article.
Here's how we implement these methods:
def create_external_card(self, card, changes, section, board, board_group, collection):
data = self.convert_card_to_article(card, section, board)
url = "https://api.intercom.io/articles"
# we return the Intercom article's ID.
return requests.post(url, json=data, headers=self.get_headers()).json().get("id")
def update_external_card(self, external_id, card, changes, section, board, board_group, collection):
data = self.convert_card_to_article(card, section, board)
url = "https://api.intercom.io/articles/%s" % external_id
# this method returns the response object so the SDK will know
# if the API call to update the article was successful.
return requests.put(url, json=data, headers=self.get_headers())
One makes the POST call to create an Intercom article, the other makes the PUT call to update the article.
When a new Card is created, the SDK knows to call create_external_card
. We return the Intercom article's ID and the SDK remembers it. When that Card is updated in Guru, the SDK will know to call update_external_card
and it'll provide the Intercom article ID (as the external_id
parameter).
To format the JSON payload for these calls, we define a method called convert_card_to_article
, which converts a Guru Card object to the format Intercom expects. Here's how that's implemented:
def convert_card_to_article(self, card, section, board):
data = {
"title": card.title,
"author_id": 5056532,
"body": card.content,
"state": "published",
}
# if the card is on a section, that's its parent in Intercom.
# if it's on a board but not a section, the board is its parent in Intercom.
if section:
data["parent_id"] = self.get_external_id(section.id)
data["parent_type"] = "section"
elif board:
data["parent_id"] = self.get_external_id(board.id)
data["parent_type"] = "collection"
return data
Finding Intercom collections and sections
There are two ways the SDK can be aware of an external object:
- It created it and remembers its external ID.
- It checks for an existing object and finds one whose name matches.
Our sample Intercom publishing script does not create or update Intercom collections or sections, it simply expects they'll already exist. So, when the SDK sees a Board in Guru and doesn't know its Intercom ID, it calls the find_external_board
method. This method gets a list of Intercom collections and checks if any match the name of our Board. Here's how that's implemented:
def find_external_board(self, guru_board):
intercom_collections = self.get_all("https://api.intercom.io/help_center/collections")
for intercom_collection in intercom_collections:
if intercom_collection["name"].lower() == guru_board.title.lower():
return intercom_collection["id"]
When we create an article, we need to set its parent_id
to be the Intercom ID of the collection or section and this is how we know that ID.
How the Script stores data
The script needs to remember some information from one run to the next, including:
- What cards have been published.
- Which version of each Card was published.
- The Intercom article ID that corresponds to each Guru Card.
- The Intercom IDs for other objects.
All of this metadata is stored in a JSON file called IntercomPublisher.json
. It's written to the script's working directory. Make sure you don't lose this file -- if you do, the script won't know which Cards have been published before and may create duplicate articles.
Publishing to other third-party platforms
In addition to Intercom, we also have examples that publish to Readme and Salesforce. To publish to another platform not listed here, you'll need to figure out all the things we covered including:
- Which objects are being published and what they'll become. For example, does a Guru Board correspond to anything in the system you're publishing to?
- Implement the API calls to create and update objects in the other system.
Updated 11 months ago