Discourse Web Page Watermark

This theme component adds a watermark to the page.

It is possible to add any of the following information:

  • a short text message
  • the username currently logged in
  • the timestamp the page was rendered

Several settings allow customizing how and when the watermark will be rendered:

  • show_watermark_in_background: If enabled will generate and display a watermark on the page.

  • scroll_enabled: If enabled the watermark will be scrolled with the page.

  • only_in_categories: List of categories in which the watermark should be displayed.

  • except_in_categories: List of categories in which the watermark should not be displayed.

  • only_in_tags: List of tags in which the watermark should be displayed.

  • except_in_tags: List of tags in which the watermark should not be displayed.

  • if_site_title_matches: Display watermark only if site title matches this regular expression. See Discourse Web Page Watermark - #5 by pfaffman for an use case.

  • or_if_url_matches: OR display the watermark if URL matches any of the regular expressions in the list. Note that the URL tested does not include the host name.

  • tile_width: The width (in px) of the tile that contains the watermark information.

  • tile_height: The height (in px) of the tile that contains the watermark information.

  • color: The color of the watermark text.

  • text_align: How the text should be aligned relative to x,y coordinates when drawn.

  • text_rotation: The angle in which the text should be rotated relative to x,y coordinates when drawn.

  • display_text: Text to be rendered in the watermark.

  • display_text_font: The font used to render the text (parsed as CSS font value).

  • display_text_x: The x-axis coordinate of the point at which to begin drawing the text in the tile canvas, in pixels.

  • display_text_y: The y-axis coordinate of the point at which to begin drawing the text in the tile canvas, in pixels.

  • display_username: If enabled the watermark will render the current username.

  • display_username_font: The font used to render the username (parsed as CSS font value).

  • display_username_x: The x-axis coordinate of the point at which to begin drawing the username in the tile canvas, in pixels.

  • display_username_y: The y-axis coordinate of the point at which to begin drawing the username in the tile canvas, in pixels.

  • display_timestamp: If enabled the watermark will render the timestamp the page was rendered.

  • display_timestamp_format: How the timestamp will be formatted. For information about the valid formats, please refer to Moment.js | Docs.

  • display_timestamp_font: The font used to render the timestamp (parsed as CSS font value).

  • display_timestamp_x: The x-axis coordinate of the point at which to begin drawing the timestamp in the tile canvas, in pixels.

  • display_timestamp_y: The y-axis coordinate of the point at which to begin drawing the timestamp in the tile canvas, in pixels.


  • If you intend to add a watermark to your forum instance you probably want to tag screenshots taken from it. Be it so that they can be traced back to you or to discourage your users to take screenshots and post on social media for example.
    But it is important to be aware that adding the watermark will hurt readability. There is a trade-off to be made between UX and having it.

  • The watermark is rendered in a div below the page. Depending on your theme the components above may cover it, so if you choose to add it to your page your theme must have a lot of transparency. It is possible though to place it over all the components changing z-index with CSS. You should also adjust mix-blend-mode to improve visibility.

div#watermark-background {
  z-index: 99999;
  mix-blend-mode: multiply;
  • This component comes with sensible defaults that should work well with most light themes. Adding a watermark to dark themes is tricky though since it will probably have more impact on readability. I strongly encourage you to tweak the settings and CSS to find what works best in your case.

  • Since the watermark is rendered in a div any user that knows how to use the Developer Tools in the browser can hide it. It will do the intended job for probably 99% of the non-technical users but is important to be aware that it is not a foolproof solution.


desktop view:

mobile view:


  • 2022-01-12: Added new settings to control when the watermark is displayed.

Can it be category based? Some of us might have a certain category only that needs a watermark.


Oh, I see, I got this mixed up with watermarks for images. I’ll edit the title so it is more clear. Kind of an unusual use case… I’m not aware of any websites that watermark every web page.


Nice idea, I’ll do my best to develop this functionality soon.

@codinghorror, thank you for clarifying the title.

I agree that it is an unusual use case. As it is right now I think it is useful mostly for private forums in enterprises with a paranoiac security department, like companies in the financial sector.

It was a first MVP. I’ll add functionality from the feedback received from the community.

Hopefully, I’ll be able to add soon the category based filter that Mr. X suggested and that will make it more useful to a broader audience.

1 Like

I just submitted a PR: skip display if title matches by pfaffman · Pull Request #1 · megothss/discourse-watermark · GitHub

This adds a theme setting include_if_title_matches, which is empty by default. If the setting is empty, then nothing is changed.

If the setting has a value, SiteSetting.title must match in order for the watermark to display.

Use case is to have the watermark display on a staging site, but not production without requiring changes to the database. Setting include_if_title_matches to “staging” and having “staging” in SiteSetting.title of the staging site (set in an ENV variable so it persists when the production database is restored to it), the watermark displays on staging site but not on production.

With this change, I’ll install this on every site that has a staging site.

1 Like

I’ve merged it today. Tweaked it slightly. The setting name was renamed to if_site_title_matches.

Can you try and check if the latest commit works in your older instances?

I’ve just released a new version that allows the watermark to be displayed in specific categories, tags, or URLs.

With the new options, I think it will cover much more use cases.


I can confirm that it works on both my production and staging sites; the former was working with Discourse.siteSettings.xxx when I was working on this (I’m about to do an upgrade that I think might change that).

It’s a big help to see my staging site with the watermark on it. Thanks for the theme!


Is it possible to add an option to create a (functionally) invisible watermark? Say, one or two color values off from the background, and under everything else? We could then look at any screenshot and look for those color values to discover the username text.

Use case is not to dissuade screenshots but to find out which user is screenshotting and distributing posts from a private forum.

Alternatively, since our forum uses auto light/dark switching, is it possible to run two copies of the theme in order to hard code the color values? Or perhaps make the watermark color a per-theme setting?

Thanks for this. Might be a perfect solution for us.

1 Like

Maybe if you can dissuade them then they’ll stop and it won’t matter who it was?

I think having it change the color depending on the current theme will be difficult. If what you want is to try to catch someone by having a secret watermark then your best bet would be to disable the other theme.

1 Like


Theoretically, it is possible. But I would test it carefully before using it in production. Since in your use case there will be almost no contrast between the watermark and the background color there is a pretty good chance that this information may get lost in compression depending on format and the settings applied when uploaded.

The primary use case for this component is to dissuade the screenshots but you can try your approach and see if works. That would be a use case I’ve never thought about before.

It is possible to use this component with both light and dark themes simultaneously. It is a use case I thought about when developing it. You don’t even need to run multiple copies of the same component.

The color setting does support using a CSS variable. For example, the default value for this setting is var(--primary-low).

So as long as a CSS variable set with the proper colors is used in all the themes you want to be watermarked. You should be good to go!

If you try, please let me know if it works as you expected.


Thanks, this clears up a lot of things!

I ran into an issue when trying the variable route.

Our only theme is the light theme, which uses the light and dark color palettes for its auto dark mode.

I can add a variable “–secondary-watermark” to the light theme css, but it doesn’t change when using the dark color palette on the light theme.

I can’t figure out how to add the variable to the color palette rather than the theme, so as a result, the light theme’s override only works with the light color palette, and when the color palette shifts automatically to dark, the watermark becomes instantly visible.

It’s a weird quirk that I had to think about for a while. Offhand, do you know if you can perform calculations with a variable? Such that I could define --secondary-watermark as --secondary minus 10? Or something like that? If so, I think that would do it.

Our use case is admittedly a little niche. I doubt that a visible watermark would dissuade because folks would try and figure out how to get around it. We’re a closed membership group and need to be able to kick out the people that spread screenshots around. That’s more important to us.

Thanks again!

1 Like

I got it using the if is-light-color-scheme function. Works exactly as expected. Thanks!