Skip to content

Instantly share code, notes, and snippets.

@tobiaslins
Last active September 27, 2023 15:19
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save tobiaslins/e0d0d767905f6fc0f13369616d596be9 to your computer and use it in GitHub Desktop.
Save tobiaslins/e0d0d767905f6fc0f13369616d596be9 to your computer and use it in GitHub Desktop.
Notion Custom Domain using Cloudflare Workers + Splitbee Analytics
const MY_DOMAIN = "help.splitbee.io"
const START_PAGE = "https://www.notion.so/splitbee/Help-Center-bbf26e2b70574901b9c98e5d11e449de"
addEventListener('fetch', event => {
event.respondWith(fetchAndApply(event.request))
})
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, HEAD, POST,PUT, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
}
function handleOptions(request) {
if (request.headers.get("Origin") !== null &&
request.headers.get("Access-Control-Request-Method") !== null &&
request.headers.get("Access-Control-Request-Headers") !== null) {
// Handle CORS pre-flight request.
return new Response(null, {
headers: corsHeaders
})
} else {
// Handle standard OPTIONS request.
return new Response(null, {
headers: {
"Allow": "GET, HEAD, POST, PUT, OPTIONS",
}
})
}
}
async function fetchAndApply(request) {
if (request.method === "OPTIONS") {
return handleOptions(request)
}
let url = new URL(request.url)
let response
if (url.pathname.startsWith("/app") && url.pathname.endsWith("js")) {
// skip validation in app.js
response = await fetch(`https://www.notion.so${url.pathname}`)
let body = await response.text()
try {
response = new Response(body.replace(/www.notion.so/g, MY_DOMAIN).replace(/notion.so/g, MY_DOMAIN), response)
response.headers.set('Content-Type', "application/x-javascript")
console.log("get rewrite app.js")
} catch (err) {
console.log(err)
}
} else if ((url.pathname.startsWith("/api"))) {
// Forward API
response = await fetch(`https://www.notion.so${url.pathname}`, {
body: request.body, // must match 'Content-Type' header
headers: {
'content-type': 'application/json;charset=UTF-8',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
},
method: "POST", // *GET, POST, PUT, DELETE, etc.
})
response = new Response(response.body, response)
response.headers.set('Access-Control-Allow-Origin', "*")
} else if (url.pathname === `/`) {
// 301 redrict
let pageUrlList = START_PAGE.split("/")
let redrictUrl = `https://${MY_DOMAIN}/${pageUrlList[pageUrlList.length - 1]}`
return Response.redirect(redrictUrl, 301)
} else {
response = await fetch(`https://www.notion.so${url.pathname}`, {
body: request.body, // must match 'Content-Type' header
headers: request.headers,
method: request.method, // *GET, POST, PUT, DELETE, etc.
})
response = new Response(response.body, response)
}
return appendSplitbee(response)
}
class ElementHandler {
element(element) {
element.append(`<script async src="https://cdn.splitbee.io/sb.js"></script>`, {
html: true
})
}
}
async function appendSplitbee(res) {
res.headers.delete("Content-Security-Policy")
return new HTMLRewriter().on('body', new ElementHandler()).transform(res)
}
@tobiaslins
Copy link
Author

  1. Create a worker with the script above.
  2. Replace the 2 variables at the top with your domain and your notion URL
  3. Go to Cloudflare -> DNS and add an A record for the domain you entered before to 192.0.2.1
    image
  4. Next map the domain to the previously created worker
    image
  5. Done :)

@mntnrk
Copy link

mntnrk commented Oct 29, 2020

Just tried this script, unfortunately, images do not load

@juan-fintech
Copy link

Just tried this script, unfortunately, images do not load

That's because Notion blocks requests from external services of their images (in this case the worker/custom URL).

  1. Upload the images on imgur (or similar)
  2. Replace the Notion images with the imgur links

And you should be good to go.

@TheRedstoneRadiant
Copy link

TheRedstoneRadiant commented Jun 18, 2022

image
Followed the steps. It works perfectly.

However, any idea how to fix this?

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