Was this page helpful?

Functions EAP

Table of contents

Note: This feature is currently only supported by our GraphQL API and available through our Early Access Program (EAP). To learn more about GraphQL in Contentful, see the Getting started with GraphQL documentation.

What are Functions?

Functions are serverless functions that run on Contentful’s delivery infrastructure. Some of our marketplace apps already have out-of-the-box support for External references such as Shopify, Commercetools and Cloudinary. If you want to fetch additional content from different resources, you can use the Functions feature to connect to external systems and enrich the response of the GraphQL request issued through Contentful's GraphQL API.

Examples

Function Command Description
function-potterdb npx create-contentful-app
--example
function-potterdb
This example serves as a Function for Contentful. It is designed to proxy GraphQL requests to PotterDB.
function-potterdb-rest-api npx create-contentful-app
--example
function-potterdb-rest-api
This example also serves as a Function but is specifically tailored for wrapping a REST API in a GraphQL response. It's useful when you have a RESTful service, and you want to provide a GraphQL interface for it in your Function.
function-mock-shop npx create-contentful-app
--example
function-mock-shop
This Function example uses Mock Shop API which is a fake e-commerce platform built by Shopify. You can also follow the our tutorial for this example.

The following diagram displays the Function request flow:

Functions request flow

The Function event handler can parse two different types of events:

  1. GraphQL field mapping event – the information returned by your function for this event is used to decide which GraphQL type is exposed on the additional _data field.
  2. GraphQL query event - your function will receive this event whenever we want to get data for a GraphQL request. This includes introspection queries.

The Function event handler can return two different types of responses:

  1. Field mapping response.
  2. Query response.

Each field that is configured with Functions, must map to a schema. We need to know the relation with the field and the corresponding GraphQL type in the Function. Therefore, the field mapping response should include a field mapping for each field.

Given the schema below:

type Query {
  product(id: String!): Product
}

type Product {
  title: String!
  description: String
  inStock: Int!
}

Here is the typing for GraphQLFieldMapping:

type GraphQLFieldTypeMapping = {
  contentTypeId: string
  fieldId: string
  graphQLOutputType: string
  graphQLQueryField: string
  graphQLQueryArguments: Record<string, string>
}

GraphQLFieldTypeMapping would have the following values for the product field:

Value Description
contentTypeId: 'Shop' Content type ID that includes the field with Resolve content on delivery checkbox enabled.
fieldId: 'product' Field ID that includes the field with Resolve content on delivery checkbox enabled.
graphQLQueryField: 'product' Field name in the query object of the given GraphQL schema.
graphQLOutputType: 'Product' The GraphQL type that you want to attach to our _data field.
graphQLQueryArguments: { id: '' } Arguments that match for the field. id matches the argument for the product field and the empty value states that the data from the field should be passed as is.

The information coming in the event.fields array in the field mapping event is driven by the annotations that are added to the field once you enable Resolve content on delivery checkbox.

To get the schema, we run an introspection query that ends up triggering the graphql.query event. Note that this might happen repeatedly, and not when you install an app.

Limitations

  • You can only have one Function per custom Contentful App defined.
  • A Function has a maximum execution time of 5 seconds.
  • Functions run only for uncached requests.
  • Functions are only available for private apps.
  • Functions can only be used with short Text or JSON object field types.
  • This feature allows you to integrate with external GraphQL APIs. It is also possible to integrate with external REST APIs, but you will need to provide your own GraphQL server implementation. You can look at our PotterDB for REST example example to see the REST API implementation.
NOTE: In the event your Function times out, we will not retry again.

Get started with Functions

To build a custom Function:

  1. Create a custom Contentful App.
  2. Generate a Content Management API (CMA) Access Token.
  3. Set up your app. To scaffold a new Contentful app with TypeScript support and a Function, run the following command: npx @contentful/create-contentful-app@latest my-fn --function external-references. Note that my-fn is the name of your app. You can replace this with your desired name.
  4. Define your schema.
  5. Add your environment variables (like the CMA token) to an .env file in the root of your project. To keep your secrets safe, make sure you include the .env line in your .gitignore file.
  6. Build your app by running the following command: npm run build.
  7. Upload your app to Contentful by running the following command: npm run upload-ci.
  8. Install your app.
  9. Create a content type.

IMPORTANT: To use the Functions, make sure you select your app while configuring your content type and enable the Resolve content on delivery checkbox.

Screenshot of Functions

  1. Create an entry.
  2. Make a GraphQL request. You can use the GraphQL Playground app to try this easily.
query {
  topicProduct(id: "ENTRY_ID") {
    myField
    myField_data {
      foo
    }
  }
}

Within the topicProduct content type, there is a field named myField which represents the content within topicProduct. The query also contains a reference to myField_data. The _data suffix in the field name implies that it is intended for use with functions. Functions are custom functions that retrieve content, and the _data suffix is a convention to signify that the field is designed to access content fetched through these functions. The foo type comes from the schema used in the function implementation.

Here is an example Response with resolved data from the function:

{
  "data": {
    "topicProduct": {
      "myField": "this is a test",
      "myField_data": {
        "foo": "hello world"
      }
    }
  }
}

Inspect Function invocations and logs

To get a better understanding of how your Function is performing, you can inspect the invocations and log output. You can do this by navigating to the App configuration page in the Contentful web app and selecting the Functions tab. Open the menu of the function you want to inspect and select View logs.

Function logs menu item

On the Function logs page you will need to select the space and environment you have installed the app in. This will load a list of all invocations of the function in the selected space and environment. You can click on an invocation to see the log output of the function.

Function invocations table

At the top of the drawer you can expand the Event section to see the event that triggered the function. Below that you will see the log output of the function.

The log severity is based on the log method used in the function. console.log will show severity info, console.warn will show severity warn, and console.error will show severity error. You can utilise this to quickly find relevant logs in the table that lists all the invocations.

Function invocation logs

Feedback

Our Product team highly welcomes feedback for all our features. To share your feedback, you can fill in this form.