Was this page helpful?

Delivery 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 Delivery Functions?

Delivery 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 Delivery functions feature to connect to external systems and enrich the response of the GraphQL request issued through Contentful's GraphQL API.

The following diagram displays the Delivery function request flow:

Delivery functions request flow

The delivery 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 delivery function event handler can return two different types of responses:

  1. Field mapping response.
  2. Query response.

Each field that is configured with delivery functions, must map to a schema. We need to know the relation with the field and the corresponding GraphQL type in the delivery 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 delivery function per custom Contentful App defined.
  • A delivery function has a maximum execution time of 5 seconds.
  • Delivery Functions run only for uncached requests.
  • Delivery Functions are only available for private apps.
NOTE: In the event your delivery function times out, we will not retry again.

Get started with Delivery Functions

To build a custom delivery 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 delivery function, run the following command: npx @contentful/create-contentful-app@latest my-del-fn --typescript --delivery-function. Note that my-del-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 delivery functions, make sure you select your app while configuring your content type and enable the Resolve content on delivery checkbox.

Screenshot of Delivery 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 delivery functions. Delivery 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 delivery functions. The foo type comes from the schema used in the delivery function implementation.

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

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

Examples

Delivery function Command Description
hosted-delivery-function-potterdb npx create-contentful-app --example hosted-delivery-function-potterdb This example serves as a hosted delivery function for Contentful. It is designed to proxy GraphQL requests to PotterDB.
hosted-delivery-function-potterdb-rest-api npx create-contentful-app --example hosted-delivery-function-potterdb-rest-api This example also serves as a hosted delivery 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 delivery function.

Feedback

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