const FAVICON_ATTR = 'data-business-favicon' const DEFAULT_FAVICON_HREF = '/favicon.png' function removeIconLinks(root: ParentNode = document.head) { root .querySelectorAll( 'link[rel="icon"], link[rel="shortcut icon"], link[rel="apple-touch-icon"]', ) .forEach((node) => node.remove()) } function appendIconLinks(href: string, cacheBust: boolean) { const resolved = cacheBust ? href.includes('?') ? `${href}&v=${Date.now()}` : `${href}?v=${Date.now()}` : href for (const rel of ['icon', 'apple-touch-icon'] as const) { const link = document.createElement('link') link.setAttribute(FAVICON_ATTR, 'true') link.rel = rel link.href = resolved if (rel === 'icon') { link.type = 'image/png' link.sizes = '48x48' } document.head.appendChild(link) } } /** Sets browser tab favicon links for the current tenant. Pass null to restore the app default. */ export function applyDocumentFavicon(url: string | null | undefined) { if (typeof document === 'undefined') return removeIconLinks() const href = url?.trim() if (!href) { appendIconLinks(DEFAULT_FAVICON_HREF, false) return } // Bust browser favicon cache when the logo/favicon media URL changes. appendIconLinks(href, true) }