Files
OpenFrontIO/src/client/components/HomeFooterAd.ts
T
Evan 5396931909 add footer ad to homepage (#3385)
Ad a footer ad to the bottom of the homescreen


<img width="1568" height="984" alt="Screenshot 2026-03-08 at 2 28 05 PM"
src="https://github.com/user-attachments/assets/a8009e37-778e-47f0-add8-42885d4f0c11"
/>

<img width="716" height="834" alt="Screenshot 2026-03-08 at 2 28 56 PM"
src="https://github.com/user-attachments/assets/5e910d6a-5019-4e06-ad9a-8980470371ca"
/>

<img width="862" height="834" alt="Screenshot 2026-03-08 at 2 29 31 PM"
src="https://github.com/user-attachments/assets/85e87052-ff7a-4266-8a2d-432831e3c7d6"
/>




## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2026-03-09 09:31:02 -07:00

87 lines
2.1 KiB
TypeScript

import { LitElement, html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
export const FOOTER_AD_MIN_HEIGHT = 880;
const FOOTER_AD_TYPE = "standard_iab_head2";
const FOOTER_AD_CONTAINER_ID = "home-footer-ad-container";
@customElement("home-footer-ad")
export class HomeFooterAd extends LitElement {
@state() private shouldShow: boolean = false;
createRenderRoot() {
return this;
}
connectedCallback() {
super.connectedCallback();
this.style.display = "contents";
document.addEventListener("userMeResponse", this.onUserMeResponse);
}
disconnectedCallback() {
super.disconnectedCallback();
document.removeEventListener("userMeResponse", this.onUserMeResponse);
this.destroyAd();
}
private onUserMeResponse = () => {
const isDesktop = window.innerWidth >= 640;
if (
!window.adsEnabled ||
(isDesktop && window.innerHeight < FOOTER_AD_MIN_HEIGHT)
) {
return;
}
this.shouldShow = true;
this.updateComplete.then(() => {
this.loadAd();
});
};
private loadAd(): void {
if (!window.ramp) {
console.warn("Playwire RAMP not available for footer ad");
return;
}
try {
window.ramp.que.push(() => {
try {
window.ramp.spaAddAds([
{ type: FOOTER_AD_TYPE, selectorId: FOOTER_AD_CONTAINER_ID },
]);
console.log("Footer ad loaded:", FOOTER_AD_TYPE);
} catch (e) {
console.error("Failed to add footer ad:", e);
}
});
} catch (error) {
console.error("Failed to load footer ad:", error);
}
}
private destroyAd(): void {
try {
window.ramp.destroyUnits(FOOTER_AD_TYPE);
console.log("successfully destroyed footer ad");
} catch (e) {
console.error("error destroying footer ad", e);
}
}
render() {
if (!this.shouldShow) {
return nothing;
}
return html`
<div
id="${FOOTER_AD_CONTAINER_ID}"
class="flex justify-center items-center w-full pointer-events-auto [&_*]:!m-0 [&_*]:!p-0"
style="margin: 0; padding: 0; line-height: 0;"
></div>
`;
}
}