diff --git a/db/knex_migrations/2023-10-13-1200-add-custom-html.js b/db/knex_migrations/2023-10-13-1200-add-custom-html.js
new file mode 100644
index 000000000..2e0315240
--- /dev/null
+++ b/db/knex_migrations/2023-10-13-1200-add-custom-html.js
@@ -0,0 +1,14 @@
+exports.up = function (knex) {
+ // Insert column for custom HTML code
+ return knex.schema
+ .alterTable("status_page", function (table) {
+ table.text("custom_html").nullable().defaultTo(null);
+ });
+};
+
+exports.down = function (knex) {
+ return knex.schema
+ .alterTable("status_page", function (table) {
+ table.dropColumn("custom_html");
+ });
+};
diff --git a/server/model/status_page.js b/server/model/status_page.js
index 528d1dd49..d97ab3a61 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -66,6 +66,10 @@ class StatusPage extends BeanModel {
head.append($(escapedGoogleAnalyticsScript));
}
+ if (process.env.UPTIME_KUMA_ALLOW_CUSTOM_HTML === "1") {
+ head.append(statusPage.customHtml);
+ }
+
// OG Meta Tags
let ogTitle = $("").attr("content", statusPage.title);
head.append(ogTitle);
@@ -247,6 +251,7 @@ class StatusPage extends BeanModel {
showPoweredBy: !!this.show_powered_by,
googleAnalyticsId: this.google_analytics_tag_id,
showCertificateExpiry: !!this.show_certificate_expiry,
+ customHtml: this.custom_html
};
}
@@ -270,6 +275,7 @@ class StatusPage extends BeanModel {
showPoweredBy: !!this.show_powered_by,
googleAnalyticsId: this.google_analytics_tag_id,
showCertificateExpiry: !!this.show_certificate_expiry,
+ customHtml: this.custom_html
};
}
diff --git a/server/socket-handlers/status-page-socket-handler.js b/server/socket-handlers/status-page-socket-handler.js
index 0804da15d..e3e603a12 100644
--- a/server/socket-handlers/status-page-socket-handler.js
+++ b/server/socket-handlers/status-page-socket-handler.js
@@ -167,6 +167,7 @@ module.exports.statusPageSocketHandler = (socket) => {
statusPage.show_certificate_expiry = config.showCertificateExpiry;
statusPage.modified_date = R.isoDateTime();
statusPage.google_analytics_tag_id = config.googleAnalyticsId;
+ statusPage.custom_html = config.customHtml;
await R.store(statusPage);
diff --git a/src/lang/en.json b/src/lang/en.json
index fcf46ff4a..f2d672c0c 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -776,6 +776,9 @@
"wayToGetClickSendSMSToken": "You can get API Username and API Key from {0} .",
"Custom Monitor Type": "Custom Monitor Type",
"Google Analytics ID": "Google Analytics ID",
+ "Custom HTML": "Custom HTML",
+ "customHtmlEnvVar1": "The environment variable",
+ "customHtmlEnvVar2": "must be set to",
"Edit Tag": "Edit Tag",
"Server Address": "Server Address",
"Learn More": "Learn More",
diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue
index 53d0781d7..006dddb96 100644
--- a/src/pages/StatusPage.vue
+++ b/src/pages/StatusPage.vue
@@ -104,6 +104,15 @@
UPTIME_KUMA_ALLOW_CUSTOM_HTML
{{ $t("customHtmlEnvVar2") }} 1
.
+