In this page

    Plugin SDK > Customize record presentation

    Customize record presentation

    While the DatoCMS interface does offer basic controls for specifying which fields of a model should be used as the record title and "image preview" within the interface, you may encounter scenarios where you need more advanced control over the presentation of your content.

    To address this, you can use the buildItemPresentationInfo hook, which enables you to customize the presentation of your records according to your specific needs. This level of flexibility empowers you to create a unique and tailored user experience that aligns with your goals.

    The buildItemPresentationInfo hook can be used in numerous ways. For example, you can:

    • Combine multiple fields to present a record;

    • Generate a preview image on the fly;

    • Perform asynchronous API requests to third parties to compose the presentation.

    These are just a few examples of what you can do with the buildItemPresentationInfo hook. The possibilities are limitless, and you can use this hook to create the exact presentation you need.

    The buildItemPresentationInfo hook is called everytime a record needs to be presented, and it can return an object with title and imageUrl attributes, or undefined, if the plugin does not want to interfere with the default presentation:

    import { connect, Item, OnBootCtx } from "datocms-plugin-sdk";
    connect({
    async buildItemPresentationInfo(item: Item, ctx: OnBootCtx) {
    return {
    title: '',
    imageUrl: '',
    }
    },
    });
    imageUrl can also be a Data URL

    While the imageUrl attribute normally is a normal URL starting with https://, you can also pass a Data URL. Data URLs can be useful to generate an image on-the-fly in JavaScript (for example, using canvases).

    A basic example

    Suppose that one of the models in a DatoCMS project is used to represent products in a ecommerce frontend, and that each product record in DatoCMS is linked to a particular Shopify product via its handle.

    Shopify holds information like inventory availability, prices and variant images. We don't want to replicate the same information in DatoCMS, but it would be nice to show them inside the DatoCMS interface.

    Since the buildItemPresentationInfo hook can be an async function, we can easily make a fetch call to the Shopify Storefront API and use this information:

    import { connect, Item, OnBootCtx } from "datocms-plugin-sdk";
    type ProductRecord = Item & {
    attributes: {
    shopify_product_handle: string;
    }
    }
    function isProductRecord(item: Item, ctx: OnBootCtx): item is ProductRecord {
    return ctx.itemTypes[item.relationships.item_type.data.id]?.attributes.api_key === 'product';
    }
    connect({
    async buildItemPresentationInfo(item: Item, ctx: OnBootCtx) {
    // we only want to tweak the presentation on product records
    if (!isProductRecord(item, ctx)) {
    return undefined;
    }
    const { title, imageUrl, availableForSale } = await fetchShopifyProduct(
    item.attributes.shopify_product_handle,
    ctx.plugin,
    );
    return {
    title: `${title} (${availableForSale ? '🛍️' : '🚫'})`,
    imageUrl,
    }
    },
    });

    To perform the actual API call to Shopify, we need an API token and the Shopify store domain. Both can be specified by the final user by adding some settings to the plugin.

    The final fetchShopifyProduct function:

    import { Plugin } from "datocms-plugin-sdk";
    type PluginParameters = {
    shopifyDomain: string;
    shopifyAccessToken: string;
    }
    async function fetchShopifyProduct(handle: string, plugin: Plugin) {
    const parameters = plugin.attributes.parameters as PluginParameters;
    const res = await fetch(
    `https://${parameters.shopifyDomain}.myshopify.com/api/graphql`,
    {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-Shopify-Storefront-Access-Token': `${parameters.shopifyAccessToken}`,
    },
    body: JSON.stringify({
    query: `query getProduct($handle: String!) {
    product: productByHandle(handle: $handle) {
    title
    availableForSale
    images(first: 1) {
    edges {
    node {
    src: transformedSrc(crop: CENTER, maxWidth: 200, maxHeight: 200)
    }
    }
    }
    }
    }`,
    variables: { handle },
    }),
    },
    );
    const body = await res.json();
    return {
    title: body.data.product.title,
    availableForSale: body.data.product.availableForSale,
    imageUrl: body.data.product.images.edges[0].node.src,
    };
    }

    buildItemPresentationInfo

    Use this function to customize the presentation of a record in records collections and "Single link" or "Multiple links" field.

    Properties available in context

    The following information and methods are available:

    Methods available in context

    The following information and methods are available: