DEV Community

Michael
Michael

Posted on

How to Hijack your head (HTML head tag)

Disclosure

This is aimed as a guide to add scripts or styles to the <head> tag of websites that you host and do not have access to the source or do not want to monkey patch source.

Additional note, you can ride on the free tier of CloudFlares service workers if you do not serve more than 100k requests on your foundry instance /join route.

Introduction

In this example, we will be creating a service worker on CloudFlare which gives us the option to inject a <link> element into the <head> element of a websites served HTML. For the example, we will be inject a style sheet into the <head> to change the appearance of FoundryVTT.

The link we will be applying is the style effects from Foundry VTT Prettier Login Screen by TheEpicSnowWolf.

Requirements

  • CloudFlare domain, or sub-domain, pointing to your FoundryVTT instance.
  • A hosted FoundryVTT instance that can be served by your domain or sub-domain.
  • Minimal knowledge of JavaScript.

Steps

1). Open CloudFlare and Login.

2). (If you have multiple domains) Use the drop down or the cards to select the domain your foundry instance is hosted on.

3). Click the Workers tab at the top:

Click Workers tab

4). On the Workers page, click Manage Workers

Manage Workers Button

5). On the Manage Workers page, click Create a Worker

Create a Worker

6). In the script section, lets create an element handler:

class ElementHandler {
  element(element) {
    element.append(`<link
      rel="stylesheet" 
      type="text/css" 
      data-id="foundry-login"
      href="https://cdn.jsdelivr.net/gh/TheEpicSnowWolf/Foundry-VTT-Prettier-Login-Screen@main/foundry_login.css"  
    >`, {html: true});
    console.log("injected");
  }
}
Enter fullscreen mode Exit fullscreen mode

This element handler, will consume the <head> element on the HTML dom and append a link to the foundry_login.css script found in the Foundry VTT Prettier Login Screen repository by TheEpicSnowWolf.

7). Next lets add a handle request function:

async function handleRequest(req) {
  const res = await fetch(req)

  if (res.url.includes('example.com/join')) {
    return new HTMLRewriter().on("head", new ElementHandler()).transform(res)
  }  

  return res;
}
Enter fullscreen mode Exit fullscreen mode

This function is designed to take the request, process the request, and check if the URL itself matches the /join route. In the script above, replace the example.com with your domain or sub-domain.domian.tld (ex dnd.example.com)

8). After that, add the event listener to hook into the worker API:

addEventListener("fetch", (event) => {
  event.respondWith(
    handleRequest(event.request).catch(
      (err) => new Response(err.stack, { status: 500 })
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

9). Click the Save and Deploy button:

Script plus Save and Deploy Button

10). With the script saved, click the script name in the upper right hand corner:

click script name

11). On the workers configuration page, uncheck the box that says Workers.dev route

workers.dev route

12). Use the drop down menu in the upper right hand corner to select your domain name.

Click Website domain

13). Click the Workers tab again

Click Workers tab

14). This time, click the Add Route button.

Add Route Button

15). In the Add Route screen, change the Route to be example.com or sub-domain.domian.tld with a trailing /join if you are doing this for foundry.

16). In the Worker drop down, select the new worker you created:

17). Click the save button:

Save Button

18). Finally, visit your website where the service worker is attached ❤️

Foundry with new CSS

Conclusion

This is incredibly useful for sites where you do not want to monkey with the code and instead inject other scripts. It can be used for Analytics, Authentication, and much more. The possibilities are endless! 😄

Source Code

Source code for service worker: Foundry VTT Service Worker

Shoutouts

Credit to @TheEpicSnowWolf on GitHub for putting together the CSS in the repository Foundry VTT Prettier Login Screen

Credit to Derek Johnson on StackOverflow for the original code snippet in their StackOverflow question "Inject HTML with Cloudflare worker"

Top comments (0)