The FeedFlare API (FlareAPI) allows anyone to extend our existing FeedFlare service. Provide new actions and incorporate outside services to make your content more interesting and engaging — both in your FeedBurner feed and on your website.
This document assumes you are a web application developer familiar with XML and one or more server-side programming structures, such as Perl, Cold Fusion, Java/JSP, ASP, or Ruby. Server-side language skills are required in order to create "dynamic" FeedFlare units, which are described in more detail below.
Note: In the XML code samples below, the ↵ symbol is used to indicate a linebreak used for spacing in the middle of long, unbroken string (such as a URL). If you copy and paste the code, you will want to remove this character and stitch the string back together at the point this symbol appeared.
The code that defines how FeedFlare should operate is encapsulated in a FeedFlare Unit file. This is an XML document that tells FeedBurner how to render a FeedFlare in the feed and on the site, and it identifies the communication channels that need to be established when creating an instance of a FeedFlare. Every FeedFlare unit is ultimately identified by a URL that either FeedBurner or a third party maintains.
A FeedFlare unit has two pieces of
information: catalog information and the instructions for generating an
instance of a FeedFlare. Additional attributes and behaviors will be
added over time. There are two main classifications for a FeedFlare unit: static or
dynamic. A static FeedFlare unit (represented by a <FeedFlare>
element in the unit XML) generates FeedFlare that does not change its
text or image over time, while a dynamic FeedFlare unit (represented by
a <DynamicFlare>
element in the unit XML) might change its representation based upon the
item data over time. A FeedFlare that says "Email This" would most
likely be static, while a FeedFlare that says "There are 3 comments ...
add yours now!" would be dynamic (because the number of comments would most likely increase over
time). In both cases, the flare link destination will likely be
variable based upon information from the feed or item.
Ah, Hello World, my old friend. We meet again. Let's say that we want to create a FeedFlare unit that just says "Hello, World" and nothing else. It's so featureless it doesn't even offer a link to click on, but we have to start somewhere.
Here's what this FeedFlare unit looks like:
<FeedFlareUnit>
<Catalog>
<Title>Hello World 1</Title>
<Description>A static FeedFlare unit that just shows the text "Hello, World"
</Description>
</Catalog>
<FeedFlare>
<Text>Hello, World</Text>
</FeedFlare>
</FeedFlareUnit>
To create this FeedFlare unit, we have to create an XML file and then host it somewhere so it has a URL FeedBurner can read.
Aside: Where do I put this XML file?
The XML file that describes a FeedFlare unit needs to be addressable by a public URL, so that means it needs to be hosted on a server somewhere so it can be periodically retrieved by FeedBurner. Here are suggestions for where you can host this file:
We have hosted this file at http://www.feedburner.com/fb/static/flareunits/HelloWorld1.xml. Publishers can now log in to FeedBurner, select the FeedFlare service, and enter that URL. Save the feed, take a look, and you should see your "Hello, World" nice and proud at the bottom of every feed item.
Let's do something a little more interesting. Let's create a FeedFlare unit that links to web resources that might be related to the current item. To do that, we'll need to do some variable substitution.
The neat thing about FeedFlare is that the unit has the entire context of the item (including the rest of the feed) available for
these variable substitutions. So, if you want to get the item's title, you can just put ${title}
in the text of the FeedFlare and the current item's title will be substituted in there. Another variable that is available is the item's
link: ${link}.
We'll talk about more powerful XPath variable substitutions below, but for now we can use Google's "similar pages" query and construct a FeedFlare unit like this:
<FeedFlareUnit>
<Catalog>
<Title>See Related Pages at Google</Title>
<Description>A static FeedFlare unit that links to a Google page that shows
pages that are similar to the current item</Description>
</Catalog>
<FeedFlare>
<Text>Hello, see related pages</Text>
<Link href="http://www.google.com/search?as_rq=${link}"/>
</FeedFlare>
</FeedFlareUnit>
It seems to work, and now when a reader clicks on the FeedFlare they are taken to a page with related links. You can find this file at http://www.feedburner.com/fb/static/flareunits/HelloRelated.xml.
Let's make the greeting a bit more personalized. Many times, the author or publisher's name is present in the feed. So let's do a couple of things .. let's say "Hello from (author)" and then link to the blog home page. We saw before that there are a few "shortcut" variables like title, but you as a FeedFlare developer have the full power of XPath at your disposal. You can construct XPath variable substitutions, so if you'd like the feed's title you could use an expression like ${../title}, which would get the item's parent's title, i.e. the feed title.
Now, that's not exactly true. The actual expression you'd need to use is ${../a:title}.
When you do XPath variable substitution, each element needs a "namespace prefix", and the "normal" feed elements have the prefix "a".
You also can define other namespaces to use.
"But wait," you exclaim. "There are all sorts of different feed formats. Do I have to provide different XPaths for different formats? That's sheer madness." Good question. The answer we are happy to offer is an emphatic "no." If you use XPath variable substitution, FeedBurner will automatically convert your feed to an Atom 1.0 feed behind the scenes and use that for the XPath. This doesn't mean that your RSS 2.0 feed will now be delivered as an Atom 1.0 feed; it just means that, for the purposes of doing this variable substitution, FeedBurner works on an Atom 1.0 copy of the feed to grab the appropriate information.
That's plenty of talk; let's see what this FeedFlare unit looks like:
<FeedFlareUnit>
<Catalog>
<Title>Hello World 2</Title>
<Description>A static FeedFlare unit that says hello from
the author and links to the main web page</Description>
</Catalog>
<FeedFlare>
<Text>Hello from ${(ancestor-or-self::*/a:author/a:name)[last()]}</Text>
<Link href="${../a:link[(@rel='alternate' or not(@rel))]/@href}"/>
</FeedFlare>
</FeedFlareUnit>
So, this is more complex than your average FeedFlare unit. But let's walk through it. This is a static FeedFlare, since the link and text we construct never changes. Both the text and the link are using variable substitution. There are a bunch of common XPath expressions listed in the Common XPath Expressions section of the document, but let's look at these:
${(ancestor-or-self::*/a:author/a:name)[last()]}href attribute of the feed's link with rel="alternate" or the feed's link with no rel
attribute (since if the rel attribute is not specified, it represents the alternate location ... see the rel attribute documentation for more information).
When all is said and done and we put this FeedFlare unit at some URL (we have it at http://www.feedburner.com/fb/static/flareunits/HelloWorld2.xml), we get some new FeedFlare (provided your feed has an author element specified for it):
Let's try a dynamic FeedFlare unit. How about we greet the name of the person who made the most recent comment? This is going to change over time, so we need to make this a dynamic FeedFlare unit. We're going to assume here that the publisher is using the Atom Feed Thread Extension framework, but you could also adapt this to support the wfw Comment API.
In a dynamic FeedFlare unit, you are constructing a URL that will be periodically called by FeedBurner, and it is the responsibility of that URL to return an XML document that represents a FeedFlare. That means you need to have some server-side programming language skills to be able to create dynamic FeedFlare units.
Let's look at this FeedFlare unit
<FeedFlareUnit>
<Catalog>
<Title>Hello, Visitor</Title>
<Description>Greet the person who made the most recent
comment to the current post.</Description>
</Catalog>
<DynamicFlare href="http://www.feedburner.com/fb/dynamicflares/HelloVisitor.jsp?↵
feedUrl=${a:link[@rel='replies']/@href}"/>
<SampleFlare>
<Text>Hello, Crawford Matrix. Thank you for your comment!</Text>
</SampleFlare>
</FeedFlareUnit>
When FeedBurner sees a new item and applies this FeedFlare unit to that item, it does the variable substitution to construct a URL that it will call periodically. This URL is only constructed once, but it is expected that the results that the URL returns will change over time. If an XPath variable substitution cannot be resolved (i.e., the feed is not using the Feed Thread Extension), then a FeedFlare will not be created for that item.
To continue with the example, let's say an item in the feed looks like this:
<entry>
<title>Increasingly disenchanted with backgammon</title>
<link rel="replies" type="application/atom+xml"
href="http://www.majordojo.com/2006/01/increasingly_di-comments.xml" thr:count="9" />
<link rel="service.edit" type="application/atom+xml"
href="http://www.majordojo.com/movabletype/mt-atom.cgi/weblog/blog_id=3/entry_id=1042"
title="Increasingly disenchanted with backgammon"/>
<id>tag:www.majordojo.com,2006://3.1042</id>
<published>2006-01-03T23:25:39Z</published>
...
</entry>
FeedBurner sees this item and constructs the following URL that it will call periodically:
GET
http://www.feedburner.com/fb/dynamicflares/HelloVisitor.jsp?feedUrl=http://www.majordojo↵ .com/2006/01/increasingly_di-comments.xml
(In this example, we're using a feedburner.com address for the DynamicFlare URL,
but it is expected that these will be hosted on many third party sites, including yours.) When FeedBurner calls this URL, it expects a response that contains a FeedFlare element:
<FeedFlare>
<Text>Hello, Crawford Matrix. Thank you for your comment!</Text>
<Link href="http://www.majordojo.com/2006/01/increasingly_di.php#11356"/>
</FeedFlare>
FeedBurner will make sure that the latest value for the dynamic FeedFlare unit is displayed in the feed — without the item showing up as modified. Cool, huh? The FeedFlare will also be updated on the site.
One more thing to mention about this example. You may wonder what the SampleFlare element is. When a publisher wants to add your FeedFlare unit to their feed, the SampleFlare serves as an example of what the FeedFlare might look like. FeedBurner
won't have an actual feed to use the DynamicFlare to generate a FeedFlare, so that's why a SampleFlare is
required for dynamic FeedFlare units. You can also provide a SampleFlare element with static FeedFlare units, but it's not required.
One thing to note with dynamic FeedFlare units is that, at this point, FeedBurner only supports a GET query to retrieve the FeedFlare. That means that you are somewhat limited in the information that you can pass to the DynamicFlare URL — passing in the entire content of an item, for example, will most likely result in a GET request that is too long. We plan on supporting the POST method in a later iteration, which would address this limitation, but for now you might have to get creative if you want to create a FeedFlare unit that operates on the content of an item.
As an example, let's say that you want to create a FeedFlare unit that simply displays "Monkey Alert!" if an item's content references, well, a monkey (thank you Jon Klem for this demented example). One can get creative with some XPath functions to achieve this result:
<FeedFlareUnit>
<Catalog>
<Title>Monkey Alert!</Title>
<Description>Show an alert if the post contains the word "monkey"</Description>
</Catalog>
<FeedFlare>
<Text>Monkey Alert for "${.[count((a:content//text())[contains(.,'monkey')])
> 0]/a:title}"!</Text>
</FeedFlare>
</FeedFlareUnit>
The text of this static FeedFlare unit (which is found at http://www.feedburner.com/fb/static/flareunits/MonkeyAlert.xml) will only evaluate if a content object associated with the item contains the word "monkey". I'm sure publishers are rushing right now to include the Monkey Alert FeedFlare unit in their feeds.
The best way to learn how to create a FeedFlare unit is to probably find one that pretty much does what you want, and then adapt it. To that end, FeedBurner is maintaining a list of numerous FeedFlare examples that can be "adapted" to your own needs. If you create a FeedFlare unit that you'd like to share, visit the FeedBurner for Developers forum.
Official FeedFlare: Static Examples
In this initial release of the FeedFlare API, you can test your FeedFlare code with real feeds immediately by using FeedBurner's FeedFlare Scratchpad. Also, here is a FeedFlare unit XML quick reference. While FeedBurner plans on adding a number of testing and diagnostic tools to help FeedFlare developers, here are a few tips to help developers create new FeedFlare units.
http://www.yourdomain.com/flare/myflair.xml, start out by using the URL
http://www.yourdomain.com/flare/myflair.xml?version=1 or something like
that, and then just increment the version number every time you edit
the XML file. This will force FeedBurner to retrieve the latest version
of the file when it is used for the first time.xmlns:prefix
mechanism.Since a FeedFlare unit is a static XML file, the variability comes
from,
well, variables in the link and text declarations. Basically, a
FeedFlare unit
has access to the context of the item and its feed container.
FeedBurner normalizes the item to an Atom 1.0 item with a feed
container, and the publisher can include any XPath as a variable in the
elements that support variability. We currently support XPath 1.0, but
we will upgrade to XPath 2.0 soon. Please note that the "current node"
for that XPath
expression will be the <entry> element that represents the current item. Here is a list of some common variable substitutions:
| Variable | Description |
|---|---|
${a:updated} |
The last updated date for the item, in ISO 8601 format. This is the same as ${./a:updated}. |
${a:category[1]/@term} |
The first listed category. |
${../a:title} |
The feed title. This is the same as ${/a:feed/a:title}. |
${../a:link[(@rel='alternate' or not(@rel))]/@href} |
The HTML page for this feed. |
${(ancestor-or-self::*/a:author/a:name)[last()]} |
The author's email address: the item-level takes precendence |
The Atom 1.0 namespace is available with the "a" prefix. Other namespaces can be declared on the containing element and referenced in the expression.
A few of the variables are used so often there are "shortcuts" for them:
| Variable | Description |
|---|---|
${link} |
The item link. Generally the same as ${a:link[rel='alternate']/@href} |
${title} |
The item title. Generally the same as ${a:title[type='text']} |
${feedUrl} |
The URL of the feed itself. Generally the same as ${a:feed/a:link[rel='self']/@href} |
This is the initial release of the FeedFlare API, and we'll be adding new features and functionality often. Here are some things you can look forward to in future iterations of the API:
Here is the DTD for the FeedFlare unit file:
<!ELEMENT FeedFlareUnit (Catalog, ((FeedFlare,SampleFlare?) | (DynamicFlare,SampleFlare)))><!ELEMENT Catalog (Title, Description, Link?, Author?)><!ELEMENT Title (#PCDATA)><!ELEMENT Description (#PCDATA)><!ELEMENT Link EMPTY><!ATTLIST Link href CDATA #REQUIRED><!ELEMENT Author (#PCDATA)><!ATTLIST Author email CDATA #IMPLIED><!ELEMENT FeedFlare (Text?, Image?, Link?)><!ELEMENT Text (#PCDATA)><!ELEMENT Image EMPTY><!ATTLIST Image src CDATA #REQUIRED><!ELEMENT DynamicFlare EMPTY><!ATTLIST DynamicFlare href CDATA #REQUIRED><!ATTLIST DynamicFlare method CDATA #IMPLIED><!ELEMENT SampleFlare (Text?, Image?)>And here is the DTD for the XML that is returned from a dynamic FeedFlare call:
<!ELEMENT FeedFlare (Text?, Image?, Link?)><!ELEMENT Text (#PCDATA)><!ELEMENT Image EMPTY><!ATTLIST Image src CDATA #REQUIRED><!ELEMENT Link EMPTY><!ATTLIST Link href CDATA #REQUIRED>