FullStory is expanding our platform to include more areas for programmatic data capture and application control. Our primary motivation is to give our customers more ways to analyze their users’ digital experiences and bind them more closely to business outcomes. For example, some of our retail customers want to close the loop between online and in-store purchasing behavior by pairing product search events that are captured via our browser API running in their website with in-store purchases captured via backend systems sending purchase events to our server API. Other use-cases involve batch-importing large volumes of data from customer data platforms, so that digital experience data captured by FullStory can be further enriched by other sources.
There are no limits to the possibilities for providing more value to customer data through API integrations with FullStory. But before we can begin making these possibilities a reality with new versions of our existing API, we need to establish a common API design philosophy shared among all engineers and product team members.
Our philosophy centers on two goals:
Empower any engineering team at FullStory to publish an API while still ensuring a consistent developer experience.
Provide the best developer experience possible to our customers.
We began by establishing “First Principles” for API design. These are high-level guidelines distilled from industry best practices that we discovered while researching widely adopted API ecosystems. These First Principles are the foundation that guide all of our new API development, regardless of platform (server, browser, mobile, and web hooks).
API design First Principles
🍰 Design for ease of use
Know your audience, the technologies they’re using, and the use cases that are important to them.
Focus on your audience’s use cases. What are they trying to accomplish?
Who is the persona you are building for? Build in a way that makes sense for them.
For example: ops engineers vs. growth engineers vs. data scientists
Avoid burdening consumers with unnecessary API calls and boilerplate.
Return well-documented, useful errors.
💡 Meet your customers where they are.
💯 Expose a complete API
Be thoughtful about whether a proposed feature supports the larger goals of the API.
Don’t release endpoints to deliver product features without thinking through how they will interact with the rest of the API.
Make sure you plan the time to design and build the full feature.
If you’re working on entirely new API surface areas, seek the advice of others: internal product team members, customer-facing support and sales staff, or open-source community members who are using tools that you’ve already built.
💡 If you don’t have the time, don’t do the crime.
🧭 Be predictable
Be boringly predictable and consistent. Design APIs that:
Follow common idioms in the target technologies.
Are internally consistent (field names and access patterns are identical within the API).
Are externally consistent (follow established conventions and patterns in other APIs your audience uses).
Are difficult to misuse.
💡 Don’t violate the principle of least surprise.
🦐 Keep APIs as small as possible
Don’t include API functionality that isn’t aligned with target use cases under the justification that it might be useful someday. It’s easier to increase API surface later than remove something that’s been released.
💡 When in doubt, leave it out.
📓 Provide great documentation
Make great documentation an explicit goal. Provide examples that seed good API usage. Document everything, including:
URLs, methods, interfaces, and payloads
States and state transitions (e.g. active vs. inactive or deleted)
Field optionality (which fields are required, which are not)
Field formats (e.g. date formats and units of measurement)
Possible errors or exceptions
💡 Without documentation, the implementation becomes the specification.
📈 Keep an eye on KPIs
Identify, clearly define, and monitor KPIs as part of designing and evaluating APIs. Ask yourself:
How will we know if we’ve built the right thing?
How will we know if an API is serving its purpose?
How will we make informed decisions about evolving the API?
💡 The right KPIs answer questions with data.
First Principles in action
Provide great documentation
We’ve recently launched a new developer guide that you can view here. We focused a lot of effort on organizing information on the site so that each one of our four API platforms (browser, server, mobile, and web hooks) were accessible. Each platform has its own “getting started” guide, while common capabilities such as fetching session details and capturing events are grouped together in a consistent manner across platforms in the navigation.
We will continue to evolve our developer guide by documenting API integration scenarios and developing language-specific SDKs.
Design for ease of use
The first iteration of our server API provides an endpoint for our customers to send us data about their users; typically profile data like shopper loyalty program status. The catch is that if the user had not already been identified with a browser session (via a browser API call) the server API would reject the request and the user’s data would not make it into FullStory. While this behavior satisfies some use-cases, it short-circuited others, including the ability to stage user profile data in FullStory prior to a user visiting a customer’s website or mobile app.
With our forthcoming V2 Server API, we designed for ease of use by accepting user data that had not already been captured in the course of a browser or mobile app session. This reduces the cognitive overhead required by our customers to understand under what conditions we would accept vs. reject user data. In this context, ease of use means that we significantly ease the path for our customers to send us user data (and thus simplify the path to data enrichment in FullStory).
Our APIs accept arbitrary data payloads for a few different resource types. We need to use consistent language across different platforms when referring to these arbitrary data payloads. With this in mind, we introduced a “properties” field that our customers can use to send us custom data. The idea is that once our customers understand how custom data works for one platform API, they can easily understand the concept in a different one.
For example, here’s how our customers set properties on a user in our forthcoming V2 browser API:
And here’s how this same data is set via our forthcoming V2 server API:
Our API contracts are designed to be internally consistent across platforms, which creates patterns that our customers can rely on when integrating with FullStory.
We also strive for external consistency: adhering to industry standards and widely-adopted platform idioms. Our APIs should behave in ways that our customers would recognize in the other APIs that they use. For example, our guideline for managing V2 Server API changes were inspired by guidelines established by other API providers like Microsoft, Plaid, and Stripe.
We clearly outline the conditions that qualify as a breaking change and how these changes are manifested in major version revisions, ensuring that our customers’ applications aren’t disrupted and that our customers have a path to opt-in to our latest API version.
Keep an eye on KPIs
API adoption is our main goal. Greater adoption by our customers implies that they are getting more value out of the data they are capturing with FullStory. There are a few ways to measure adoption:
General traffic volume (for example, number of calls made to APIs and amount of data transacted)
Number of FullStory integrations built by the development community
FullStory application impact
General traffic volume is fairly easy to track: they are baseline metrics that we gather for operational monitoring anyway.
To track the number of community-built integrations, we sum up the FullStory integrations built via our formal technology partners. We also keep track of open source integrations thanks to tools like the GitHub dependency graph and NPM dependents list.
Application impact metrics align more with customer behavior once data is flowing into FullStory via APIs. There are a couple of KPIs that we’ll be tracking along these lines:
Percentage of Dashboard visualizations that use API-originated data
Number of customers that deep link into the FullStory application directly from external tools
In all cases: up and to the right is good. :)
By combining general API traffic metrics and third-party integration counts with deeper insights into customer behavior in FullStory, we feel like we’ll have our bases covered around API adoption and usage.
Next up: Detailed API guidelines
Establishing First Principles is step one for our API evolution. In a follow-up article, I’ll share how we drove out platform-specific API guidelines that define rules for API interfaces and behaviors.
We’d love your feedback
We’re always striving to improve the usability of our APIs. If you have suggestions, please reach out to us here.