> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/salesforce/content-edit/watermarks.md).

# Add Watermarks to PDFs Using JavaScript

Learn how to add watermarks to documents easily with DocumentViewer's setWatermark method. Draw text or images on top of your document with just a few lines of code. Perfect for customizing and protec

Adding text or an image as a watermark on top of a document requires only a few lines of code using the [`setWatermark`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) method of DocumentViewer. This method allows you to pass an options object to draw text on top of the document or pass a custom function which will be executed with a reference to the page canvas.

{% embed url="<https://www.youtube.com/embed/Xfv_psvC468>" %}

## Draw text as watermark

To draw a watermark, use [`documentViewer.setWatermark`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) and pass an options object as shown below.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
const { documentViewer } = instance.Core;

documentViewer.setWatermark({
  // Draw diagonal watermark in middle of the document
  diagonal: {
    fontSize: 25, // or even smaller size
    fontFamily: 'sans-serif',
    color: 'red',
    opacity: 50, // from 0 to 100
    text: 'Watermark'
  },

  // Draw header watermark
  header: {
    fontSize: 10,
    fontFamily: 'sans-serif',
    color: 'red',
    opacity: 70,
    left: 'left watermark',
    center: 'center watermark',
    right: ''
  }
});
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  initialDoc: 'https://url/to/my_file.docx',
  // ...
}, viewerElement)
  .then(instance => {
    const { docViewer } = instance;
    docViewer.setWatermark({
      // Draw diagonal watermark in middle of the document
      diagonal: {
        fontSize: 25, // or even smaller size
        fontFamily: 'sans-serif',
        color: 'red',
        opacity: 50, // from 0 to 100
        text: 'Watermark'
      },
      // Draw header watermark
      header: {
        fontSize: 10,
        fontFamily: 'sans-serif',
        color: 'red',
        opacity: 70,
        left: 'left watermark',
        center: 'center watermark',
        right: ''
      }
    });
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}
{% endtabs %}

![](https://306473577-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfmJo9lQOEYOFBgOyFp26%2Fuploads%2Fgit-blob-af033d9de9f7aa2f061694009413c0bf066557c0%2Fba372531061c4584746d345a192aca0fc2b8e05d-1698x1626.png?alt=media)

## Draw custom content as watermark

The [`setWatermark`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) method also allows you to draw custom content on the page. To do this, pass a custom function to the API as a part of the options object.

For the following sample, we will use a Promise which will resolve with the watermark options object. If the document hasn't been loaded yet then DocumentViewer will wait to finish loading it until the watermark options are ready.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  initialDoc: 'https://url/to/my_file.docx',
  // ...
}, viewerElement)
  .then(instance => {
    const { documentViewer } = instance.Core;
    const path = '/samples/full-apis/TestFiles/butterfly.png'
    // Promise resolves with options object
    const promise = new Promise(resolve => {
      const img = new Image();
      const options = {
        footer: {
          fontSize: 15,
          fontFamily: 'sans-serif',
          color: 'red',
          opacity: 70,
          left: 'left watermark',
          center: 'center watermark'
        },
        custom: (ctx, pageNumber, pageWidth, pageHeight) => {
          // the pageNumber is also passed in so you could have
          // a different watermark for each page
          ctx.drawImage(
            img,
            pageWidth / 2 - img.width / 2,
            pageHeight / 2 - img.height / 2
          );
        }
      };
      img.onload = () => { 
        return resolve(options);
      };
      img.src = path;
    });
    documentViewer.setWatermark(promise);
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v7.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  initialDoc: 'https://url/to/my_file.docx',
  // ...
}, viewerElement)
  .then(instance => {
    const { docViewer } = instance;
    const path = '/samples/full-apis/TestFiles/butterfly.png'
    // Promise resolves with options object
    const promise = new Promise(resolve => {
      const img = new Image();
      const options = {
        footer: {
          fontSize: 15,
          fontFamily: 'sans-serif',
          color: 'red',
          opacity: 70,
          left: 'left watermark',
          center: 'center watermark'
        },
        custom: (ctx, pageNumber, pageWidth, pageHeight) => {
          // the pageNumber is also passed in so you could have
          // a different watermark for each page
          ctx.drawImage(
            img,
            pageWidth / 2 - img.width / 2,
            pageHeight / 2 - img.height / 2
          );
        }
      };
      img.onload = () => { 
        return resolve(options);
      };
      img.src = path;
    });
    docViewer.setWatermark(promise);
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  initialDoc: 'https://url/to/my_file.docx',
  // ...
}, viewerElement)
  .then(instance => {
    const { docViewer } = instance;
    const path = '/samples/full-apis/TestFiles/butterfly.png'
    // Promise resolves with options object
    const promise = new Promise(resolve => {
      const img = new Image();
      const options = {
        footer: {
          fontSize: 15,
          fontFamily: 'sans-serif',
          color: 'red',
          opacity: 70,
          left: 'left watermark',
          center: 'center watermark'
        },
        custom: (ctx, pageIndex, pageWidth, pageHeight) => {
          // the pageIndex is also passed in so you could have
          // a different watermark for each page
          ctx.drawImage(
            img,
            pageWidth / 2 - img.width / 2,
            pageHeight / 2 - img.height / 2
          );
        }
      };
      img.onload = () => { 
        return resolve(options);
      };
      img.src = path;
    });
    docViewer.setWatermark(promise);
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}
{% endtabs %}

![](https://306473577-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfmJo9lQOEYOFBgOyFp26%2Fuploads%2Fgit-blob-7f275a56bc53e087b8460551a2673c7a0bdd76a9%2Fa2b81da5295eab0faf0f431322f3538fecf33137-1988x1836.png?alt=media)

## Draw watermark text in custom positions

The [`setWatermark`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)`custom` argument can also be used to draw text in custom positions.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  // ...
}, viewerElement)
  .then(instance => {
    const { documentViewer } = instance.Core;
    documentViewer.setWatermark({
      custom: (ctx, pageNumber, pageWidth, pageHeight) => {
        // ctx is an instance of CanvasRenderingContext2D
        // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
        // Hence being able to leverage those properties
        ctx.fillStyle = '#ff0000';
        ctx.font = '20pt Arial';
        ctx.globalAlpha = 0.4;
    
        ctx.save();
        ctx.translate(0, pageHeight / 2);
        ctx.rotate(-Math.PI / 2);
        ctx.fillText('left side watermark', 0, 0);
        ctx.restore();
    
        ctx.save();
        ctx.translate(pageWidth, pageHeight / 2);
        ctx.rotate(Math.PI / 2);
        ctx.fillText('right side watermark', 0, 0);
        ctx.restore();
      },
    });
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v7.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  // ...
}, viewerElement)
  .then(instance => {
    const { docViewer } = instance;
    docViewer.setWatermark({
      custom: (ctx, pageNumber, pageWidth, pageHeight) => {
        // ctx is an instance of CanvasRenderingContext2D
        // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
        // Hence being able to leverage those properties
        ctx.fillStyle = '#ff0000';
        ctx.font = '20pt Arial';
        ctx.globalAlpha = 0.4;
    
        ctx.save();
        ctx.translate(0, pageHeight / 2);
        ctx.rotate(-Math.PI / 2);
        ctx.fillText('left side watermark', 0, 0);
        ctx.restore();
    
        ctx.save();
        ctx.translate(pageWidth, pageHeight / 2);
        ctx.rotate(Math.PI / 2);
        ctx.fillText('right side watermark', 0, 0);
        ctx.restore();
      },
    });
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  // ...
}, viewerElement)
  .then(instance => {
    const { docViewer } = instance;
    docViewer.setWatermark({
      custom: (ctx, pageIndex, pageWidth, pageHeight) => {
        // ctx is an instance of CanvasRenderingContext2D
        // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
        // Hence being able to leverage those properties
        ctx.fillStyle = '#ff0000';
        ctx.font = '20pt Arial';
        ctx.globalAlpha = 0.4;
    
        ctx.save();
        ctx.translate(0, pageHeight / 2);
        ctx.rotate(-Math.PI / 2);
        ctx.fillText('left side watermark', 0, 0);
        ctx.restore();
    
        ctx.save();
        ctx.translate(pageWidth, pageHeight / 2);
        ctx.rotate(Math.PI / 2);
        ctx.fillText('right side watermark', 0, 0);
        ctx.restore();
      },
    });
  });
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor)
{% endtab %}
{% endtabs %}

![](https://306473577-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfmJo9lQOEYOFBgOyFp26%2Fuploads%2Fgit-blob-7af0106509d0a3b8d7d8676a272085069e4e2f2a%2F0b7c048060133592f887ec2fe26bde9960688368-829x1177.png?alt=media)

## Draw watermark without DocumentViewer

If you're constructing your own [Document](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) instance then it also provides a [`setWatermark`](https://sdk.apryse.com/api/web/Core.Document.html#setWatermark__anchor) method.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}

<pre class="language-js" data-line-numbers><code class="lang-js">const filePath = '/webviewer-demo.pdf';
const watermarkOptions = {
 header: {
     fontSize: 15,
     color: 'blue',
     center: 'center watermark',
 },
 diagonal: {
     fontSize: 30,
     fontFamily: 'sans-serif',
     color: 'red',
     opacity: 100,
     text: 'Watermark'
 }
};
const doc = await Core.createDocument(filePath, { l: '<code class="expression">visitor.claims.wvKey || "YOUR_LICENSE_KEY"</code>'});
// Set watermark options object
doc.setWatermark(watermarkOptions);
// Draw canvas
doc.loadCanvasAsync({
 pageIndex: 0,
 getZoom: () =>  0.8,  // 80% zoom,
 drawComplete: pageCanvas => {
   // Append canvas to dom to see the result
   document.body.appendChild(pageCanvas);
 },
});
</code></pre>

[Core.createDocument](https://sdk.apryse.com/api/web/Core.html#.createDocument__anchor) [Core.Document.setWaterMark](https://sdk.apryse.com/api/web/Core.Document.html#setWatermark__anchor) [Core.Document.loadCanvasAsync](https://sdk.apryse.com/api/web/Core.Document.html#loadCanvasAsync__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}

<pre class="language-js" data-line-numbers><code class="lang-js">const filePath = '/webviewer-demo.pdf';
const watermarkOptions = {
 header: {
     fontSize: 15,
     color: 'blue',
     center: 'center watermark',
 },
 diagonal: {
     fontSize: 30,
     fontFamily: 'sans-serif',
     color: 'red',
     opacity: 100,
     text: 'Watermark'
 }
};
const doc = await CoreControls.createDocument(filePath, { l: '<code class="expression">visitor.claims.wvKey || "YOUR_LICENSE_KEY"</code>'});
// Set watermark options object
doc.setWatermark(watermarkOptions);
// Draw canvas
doc.loadCanvasAsync({
 pageIndex: 0,
 getZoom: () =>  0.8,  // 80% zoom,
 drawComplete: pageCanvas => {
   // Append canvas to dom to see the result
   document.body.appendChild(pageCanvas);
 },
});
</code></pre>

[CoreControls.createDocument](https://sdk.apryse.com/api/web/Core.html#.createDocument__anchor) [CoreControls.Document.setWaterMark](https://sdk.apryse.com/api/web/Core.Document.html#setWatermark__anchor) [CoreControls.Document.loadCanvasAsync](https://sdk.apryse.com/api/web/Core.Document.html#loadCanvasAsync__anchor)
{% endtab %}
{% endtabs %}

## Draw watermark dynamically

If you want to add a watermark or modify the existing watermark after pages are rendered, then after calling [`setWatermark`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) you will also need to call the [`refreshAll`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) and the [`updateView`](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor) methods of DocumentViewer.

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const { documentViewer } = instance.Core;
    const watermarkOptions = {...};
    documentViewer.setWatermark(watermarkOptions);
    documentViewer.refreshAll();
    documentViewer.updateView();
  })
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) [DocumentViewer.refreshAll](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) [DocumentViewer.updateView](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const { docViewer } = instance;
    const watermarkOptions = {...};
    docViewer.setWatermark(watermarkOptions);
    docViewer.refreshAll();
    docViewer.updateView();
  })
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) [DocumentViewer.refreshAll](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) [DocumentViewer.updateView](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor)
{% endtab %}
{% endtabs %}

If you are going to use a Promise then you need to call those two methods after the Promise has resolved:

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const { documentViewer } = instance.Core;
    const promise = new Promise(resolve => {
      // some asynchronous operations to generate the watermark options object
      resolve(watermarkOptions);
    });
    documentViewer.setWatermark(promise);
    documentViewer.getWatermark().then(() => {
      documentViewer.refreshAll();
      documentViewer.updateView();
    })
  })
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) [DocumentViewer.refreshAll](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) [DocumentViewer.updateView](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const { docViewer } = instance;
    const promise = new Promise(resolve => {
      // some asynchronous operations to generate the watermark options object
      resolve(watermarkOptions);
    });
    docViewer.setWatermark(promise);
    docViewer.getWatermark().then(() => {
      docViewer.refreshAll();
      docViewer.updateView();
    })
  })
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [DocumentViewer.setWaterMark](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#setWatermark__anchor) [DocumentViewer.refreshAll](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#refreshAll__anchor) [DocumentViewer.updateView](https://sdk.apryse.com/api/web/Core.DocumentViewer.html#updateView__anchor)
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/salesforce/content-edit/watermarks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
