ScreenshotConfig API

Control what to include in Cord's screenshots or provide your own screenshot


About Cord screenshots #

When users place an annotation, Cord takes a screenshot of the current viewport. The screenshot is attached to the Slack and email notifications. Screenshots are useful as they capture what the user is currently seeing. If the content of that page changes, users can still refer to the screenshot to get more context.

The screenshotConfig API allows developers to specify exactly what to screenshot: the targetElement. This element can be anywhere in the current document, not necessarily within the viewport. You can use screenshotConfig with the Thread and FloatingThreads components.

If you already have a screenshot of the page, and don't want Cord to take one, you can specify a screenshotUrlOverride. The URL can be a link to a hosted image, or a DataURL. This resource will be used as the screenshot. For best results, the provided image size should be as close as possible as the user's current viewport size.

Examples #

For the examples, we will use Cord Thread component. However, you can also use FloatingThreads.

Screenshot a specific element #

With the following snippet, the screenshot will only include our target element and its children.
React:
import { Thread } from '@cord-sdk/react';

export const Example = () => {
    const screenshotTargetRef = useRef<HTMLDivElement>(null);

    return (
        <>
            <Thread
                threadId={'<any string that is unique across your entire project>'}
                location={{ page: 'index' }}
                screenshotConfig={{ targetElement: screenshotTargetRef.current }}
            />
            <div ref={screenshotTargetRef}>Anything inside this element will be in the screenshot</div>
        </>
    );
};
Vanilla JavaScript:
const thread = document.querySelector('cord-thread');
const screenshotTarget = document.querySelector('.my-screenshot-target');
thread.screenshotConfig = { targetElement: screenshotTarget };
import { Thread } from '@cord-sdk/react';

export const Example = () => {
    const screenshotTargetRef = useRef<HTMLDivElement>(null);

    return (
        <>
            <Thread
                threadId={'<any string that is unique across your entire project>'}
                location={{ page: 'index' }}
                screenshotConfig={{ targetElement: screenshotTargetRef.current }}
            />
            <div ref={screenshotTargetRef}>Anything inside this element will be in the screenshot</div>
        </>
    );
};
Copy

Screenshot a specific element and crop it #

To more exactly control the screenshot crop, you can specify a cropRectangle. This can be useful to screenshot part of the page where there isn't a suitable common ancestor to use as a targetElement.
React:
import { Thread } from '@cord-sdk/react';

export const Example = () => {
    const screenshotTargetRef = useRef<HTMLDivElement>(null);
    // Crop 20px from the bottom of the screenshot
    const cropRectangle = { height: screenshotTargetRef.current.clientHeight - 20 };

    return (
        <>
            <Thread
                threadId={'<any string that is unique across your entire project>'}
                location={{ page: 'index' }}
                screenshotConfig={{ targetElement: screenshotTargetRef.current, cropRectangle }}
            />
            <div ref={screenshotTargetRef}>Anything inside this element will be in the screenshot</div>
        </>
    );
};
Vanilla JavaScript:
const thread = document.querySelector('cord-thread');
const screenshotTarget = document.querySelector('.my-screenshot-target');
// Crop 20px from the bottom of the screenshot
const cropRectangle = { height: screenshotTargetRef.clientHeight - 20 };
thread.screenshotConfig = { targetElement: screenshotTarget, cropRectangle };
import { Thread } from '@cord-sdk/react';

export const Example = () => {
    const screenshotTargetRef = useRef<HTMLDivElement>(null);
    // Crop 20px from the bottom of the screenshot
    const cropRectangle = { height: screenshotTargetRef.current.clientHeight - 20 };

    return (
        <>
            <Thread
                threadId={'<any string that is unique across your entire project>'}
                location={{ page: 'index' }}
                screenshotConfig={{ targetElement: screenshotTargetRef.current, cropRectangle }}
            />
            <div ref={screenshotTargetRef}>Anything inside this element will be in the screenshot</div>
        </>
    );
};
Copy
The ScreenshotConfig API pairs well with cord-annotation-allowed API. If you are restricting what can be annotated, you might also want to restrict what gets in the screenshot.

Provide your own Screenshot #

If you don't want Cord to take a screenshot of the page, you can specify an image in the form of an URL to screenshotUrlOverride. When Cord is about to take a screenshot, it will check this property. If it's defined, Cord will fetch the image and attach it to the message. For this reason, it's best to set screenshotUrlOverride as soon as you know what the screenshot should be. Note that the screenshotUrlOverride takes precedence over the targetElement.
React:
import { FloatingThreads } from '@cord-sdk/react';

export const Example = () => {
    return (
          <FloatingThreads
              location={{ page: 'index' }}
              screenshotConfig={{ screenshotUrlOverride: "https://picsum.photos/200" }}
          />
    );
};
Vanilla JavaScript:
const floatingThreads = document.querySelector('cord-thread');
floatingThreads.screenshotConfig = { screenshotUrlOverride: "https://picsum.photos/200" };
import { FloatingThreads } from '@cord-sdk/react';

export const Example = () => {
    return (
          <FloatingThreads
              location={{ page: 'index' }}
              screenshotConfig={{ screenshotUrlOverride: "https://picsum.photos/200" }}
          />
    );
};
Copy

Remove screenshotConfig #

Removing the screenshotConfig restores Cord's default screenshot behavior: screenshot the whole viewport.
React:
import { Thread } from '@cord-sdk/react';

export const Example = () => {
    return (
        <Thread
            threadId={'<any string that is unique across your entire project>'}
            location={{ page: 'index' }}
            // no screenshotConfig specified
        />
    );
};
Vanilla JavaScript:
const thread = document.querySelector('cord-thread');
const screenshotTarget = document.querySelector('.my-screenshot-target');
thread.screenshotConfig = undefined;
import { Thread } from '@cord-sdk/react';

export const Example = () => {
    return (
        <Thread
            threadId={'<any string that is unique across your entire project>'}
            location={{ page: 'index' }}
            // no screenshotConfig specified
        />
    );
};
Copy

Types #

TypeScript:
/**
* Specify what DOM element to screenshot. This overrides Cord's
* default screenshot behavior, which is to take a screenshot of
* the current viewport.
*
* You can set this to `undefined` to enable Cord's default behavior again.
*/
export type ScreenshotConfig =
| {
    /**
    * The screenshot will only include this DOM
    * element and all of its children.
    */
    targetElement: HTMLElement;
    /**
    * Crop the screenshot to a specific rectangle within the target element. 
    * All values must be specified in pixels.
    */
    cropRectangle?: Partial<{
        /** X coordinate of the top left corner of the rectangle. 
         * By default, this matches the top left corner of the `targetElement` */
        x: number;
        /** Y coordinate of the top left corner of the rectangle. 
         * By default, this matches the top left corner of the `targetElement` */
        y: number;
        /** By default, this is the width of the `targetElement` */
        width: number;
        /** By default, this is the height of the `targetElement` */
        height: number;
     }>;
    }
| undefined;
/**
* Specify what DOM element to screenshot. This overrides Cord's
* default screenshot behavior, which is to take a screenshot of
* the current viewport.
*
* You can set this to `undefined` to enable Cord's default behavior again.
*/
export type ScreenshotConfig =
| {
    /**
    * The screenshot will only include this DOM
    * element and all of its children.
    */
    targetElement: HTMLElement;
    /**
    * Crop the screenshot to a specific rectangle within the target element. 
    * All values must be specified in pixels.
    */
    cropRectangle?: Partial<{
        /** X coordinate of the top left corner of the rectangle. 
         * By default, this matches the top left corner of the `targetElement` */
        x: number;
        /** Y coordinate of the top left corner of the rectangle. 
         * By default, this matches the top left corner of the `targetElement` */
        y: number;
        /** By default, this is the width of the `targetElement` */
        width: number;
        /** By default, this is the height of the `targetElement` */
        height: number;
     }>;
    }
| undefined;
Copy

Ask Cordy