Skip to content

DRAFT: empty template for embedding custom HTML and inline javascript - #1763

Draft
kevinpapst wants to merge 1 commit into
getfider:mainfrom
kevinpapst:custom-html
Draft

kevinpapst wants to merge 1 commit into
getfider:mainfrom
kevinpapst:custom-html

Conversation

@kevinpapst

@kevinpapst kevinpapst commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ THIS PR IS MEANT AS DISCUSSION STARTER ⚠️

Many support requests ask for either Inline Javascript or Custom HTML, most talk about custom analytics tags.

I created the simplest solution I could come up with and which works for my use-case (including Umami tracking script). I know GoogleTag-Manager is supported, but GT is a privacy nightmare.

Lets start with the cons: my solution has the clear drawback that it is tailored to Docker users and does not support multi-tenants. But I wanted to have a minimalistic working solution to start the discussion.

You @mattwoberts mentioned and I agree:

We'd need to be careful about malicious use of something like this though

At first I thought about adding a textfield (like the custom css) to the admin section, but:

  • the CSP headers are rendered before the Tenant is known, so hard to patch
  • it allows to inject code at runtime, so a bug that exposes this setting could lead to XSS

I decided against it for security and complexity reasons and because I believe it solves > 90% of all requests (even stuff like this could be handled).

That's why I chose to follow the existing approach where the system admin mounts a template (like the terms and privacy pages) via docker:

services:
  fider:
    environment:
      CSP_ALLOWED_HOSTS: "https://stats.example.com"
    volumes:
      - ./custom.html:/app/views/custom.html:ro

The custom.html then can contain any HTML code, but I believe it will mostly carry inline javascript or script tags like this:

<script nonce="{{ .public.contextID }}" src="https://stats.example.com/t.js"></script>

The {{ .public.contextID }} is announced in the CSP header, so it needs to be added to the script tag. If a script is loaded from an external source, the new ENV variable CSP_ALLOWED_HOSTS also needs to be configured and point to the full URL of the script host (which will be injected in the CSP header).

As this is only done by the server administrator it is a "safe" approach.

Obviously I would add documentation for this feature, if it is accepted in one way or another.


Checklist

  • This PR is linked to a Github issue (bug fix or an agreed change).
  • New feature only: it relates to a suggestion on https://feedback.fider.io and a maintainer has confirmed on the linked issue that it's accepted onto the roadmap.
  • I've read the Contributing guide and the feature policy in discussion #1529.

@kevinpapst kevinpapst changed the title empty template for embedding custom HTML and inline javascript DRAFT: empty template for embedding custom HTML and inline javascript Nov 5, 2026
@kevinpapst
kevinpapst marked this pull request as draft November 5, 2026 16:18
@mattwoberts

mattwoberts commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

@kevinpapst I honestly don't think I would have come up with the docker solution, that's pretty neat.

The thing is, I'd love to offer this for the hosted version. But that means "Custom script" admin area. And obviously that's very risky indeed. I think I'd have to put constraints on it like own-domains only, and possibly making it paid-for only (and self-host ofc).

Another option would be we go ahead with your solution, and introduce something too that's a more user-friendly hosted-compatible way to add support for various analytics services... Plausible etc. That's possible and less open to abuse, but less flexible and also means we need to keep on top of that list of supported analytics and the script to use etc.

@kevinpapst

kevinpapst commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Yeah, I fully understand.

I also fiddled around a bit with a text box, but deleted my draft as there are two issues that needs to be discussed first:

CSP header

Your very strict CSP header needs to know every domain that is contacted. Which is positive, don't get me wrong.
But the problem is the moment when the header it is created: before the tenant data is available.
The current GoogleTagManager code is a good example of that problem (if I am not wrong). It needs to be set as ENV so we can squeeze it into the header very early on.

So one of the issues to solve is the question: when do we want the header to be created? Headers can be set multiple times and the last one wins, so we could overwrite it if necessary later on, but that's a smell.

I'd recommend to move the header creation to the moment when we can access the tenant data.

What do you want to support

Having the option for custom javascript is honestly an amazing feature. Yes, it can break things, but obviously that is an Admin only feature and "with great power comes great responsibility". It would be the most powerful approach, but that question is strategic and only you can decide how far you want to open up Fider.
I do offer custom CSS and custom Javascript in Kimai SaaS and it allows for so many small customisations, you'd be surprised what people build if they get this option. It can solve so many small requests, which you don't want to build into the core product.

The next one is definitely more convenient for the end-user, is compatible with the hosted version and could easily be moved into the premium feature section: adding support for multiple analytics solutions in the Admin area.

All self-hosted analytic solutions I have seen need an identifier and the script URL, e.g. with a self-hosted Umami (great tool if you don't know it) the script looks like this:

<script defer src="https://t.example.com/script.js" data-website-id="1234-5678-9012-1234-786587658765"></script>

Matomo also needs URL and ID. Hosted solutions usually need an ID and optionally a URL So we have one or two separate textfields (ID and sometimes URL) and can parse the host from the URL and add it to the CSP very easy.

I would offer to move the current Google solution and add Umami and Matomo as a starter to the admin area.


Just to make sure we are on the same page: the second solution has a better UX, but it is not really "safer" than the first approach. In the example above nothing stops me from hosting my own code at https://t.example.com/script.js instead of the Umami script 👿

Let me know what you prefer and I will build a new prototype. I just would prefer to add my analytics script "upgrade compatible" instead of mounting a patched /base.html:/app/views/base.html:ro version into my docker image 🙈


Edit: if you feel uncomfortable with any of the solutions close the issue. I think its worth to explore the feature, but I don't mind if you reject it for now!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants