First-Visit Announcement Bar
First-Visit Announcement Bar with localStorage (No Cookies, No Frameworks)
Sometimes you want to say something to new visitors without nagging people who visit every day. A short “Welcome” message, a note about a new feature, or an important update is useful once, but gets old fast if it keeps appearing on every page.
This snippet solves that with a tiny, cookie-free announcement bar that only shows
on a visitor’s first visit (or first visit per campaign key). It uses
localStorage to remember dismissal and stays completely on the front end:
no backend, no tracking pixels, and no layout changes beyond a slim bar at the top.
What this snippet does
A tiny announcement bar that only shows on a visitor’s first visit using
localStorage. Great for “New here?” messages, promos or important
updates without nagging regulars. No cookies, no frameworks, just a small
drop-in snippet.
How it works:
- Shows a fixed bar at the top on the visitor’s first page view.
- When they click “× Close”, the bar fades out and sets a flag in
localStorage. - On future visits, the script sees the flag and never shows the bar again.
- You can change the text, link, colors and storage key in one place.
Because it lives entirely in the browser and writes a single key to
localStorage, it’s a simple way to handle one-time “welcome” style
messaging without introducing a full consent-management flow or a complex
notification system.
Installation
Install: Paste the snippet right before </body> on your page
(ideally in a common footer include if you have one). Any page that includes it
will show the bar once for visitors who haven’t dismissed it yet.
<!-- First-Visit Announcement Bar (VibeScriptz) -->
<div
id="vs-announce-bar"
class="vs-announce-bar"
data-vs-key="vs_announce_seen_main"
>
<div class="vs-announce-inner">
<span class="vs-announce-text">
New here? 👋 Check out our most popular script:
<a href="/script/dark-mode-toggle-with-local-storage-no-frameworks/">
Dark Mode Toggle
</a>
</span>
<button class="vs-announce-close" type="button" aria-label="Close">
×
</button>
</div>
</div>
<style>
/* --- First-Visit Announcement Bar (no frameworks, no cookies) --- */
.vs-announce-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9999;
background: #111;
color: #f5f5f5;
transform: translateY(-100%);
opacity: 0;
transition: transform 0.25s ease-out, opacity 0.25s ease-out;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
sans-serif;
font-size: 14px;
}
.vs-announce-visible {
transform: translateY(0);
opacity: 1;
}
.vs-announce-hiding {
opacity: 0;
}
.vs-announce-inner {
max-width: 1100px;
margin: 0 auto;
padding: 8px 12px;
display: flex;
align-items: center;
gap: 10px;
}
.vs-announce-text {
flex: 1;
line-height: 1.4;
}
.vs-announce-text a {
color: #ffd86b;
text-decoration: underline;
}
.vs-announce-text a:hover {
color: #ffe9a6;
}
.vs-announce-close {
border: 0;
background: #444;
color: #fff;
cursor: pointer;
border-radius: 999px;
width: 24px;
height: 24px;
line-height: 24px;
padding: 0;
text-align: center;
font-size: 16px;
}
.vs-announce-close:hover {
background: #666;
}
/* Slightly smaller on narrow screens */
@media (max-width: 600px) {
.vs-announce-inner {
padding: 6px 10px;
font-size: 13px;
}
}
</style>
<script>
/*
* First-Visit Announcement Bar
* - Uses localStorage only (no cookies)
* - Change data-vs-key if you want a separate bar per campaign
*/
(function () {
var bar = document.getElementById("vs-announce-bar");
if (!bar) return;
var storageKey = bar.getAttribute("data-vs-key") || "vs_announce_seen";
// If we've already seen this announcement, remove the bar and bail
try {
if (window.localStorage && localStorage.getItem(storageKey) === "1") {
bar.parentNode.removeChild(bar);
return;
}
} catch (e) {
// localStorage might be blocked; fail silently and just show the bar
}
// Show bar
bar.classList.add("vs-announce-visible");
function hideBar() {
bar.classList.remove("vs-announce-visible");
bar.classList.add("vs-announce-hiding");
// Remove from DOM after fade
setTimeout(function () {
if (bar && bar.parentNode) {
bar.parentNode.removeChild(bar);
}
}, 300);
// Remember dismissal
try {
if (window.localStorage) {
localStorage.setItem(storageKey, "1");
}
} catch (e) {}
}
// Close on button click
bar.addEventListener("click", function (evt) {
if (
evt.target.classList.contains("vs-announce-close") ||
evt.target.closest(".vs-announce-close")
) {
hideBar();
}
});
})();
</script>
Customizing the bar
Customize it:
-
Change the text and link inside
.vs-announce-textto point at your own docs, scripts, newsletter, or onboarding page. -
Tweak colors in the CSS (
background: #111;, link colors, button background) so the bar matches your site’s palette. -
Change
data-vs-keyif you want a different bar for a new promo, for examplevs_announce_black_fridayorvs_announce_new_feature. -
To make it show again for yourself, clear
localStoragefor this site or open the page in a private window / another browser profile.
Because the storage key is just a string, you can safely rotate campaigns by assigning
each one a unique key. The old key stays in localStorage as history, and
the new key controls whether the new announcement appears.
When this pattern makes sense
A first-visit announcement bar works well for:
- Highlighting one “flagship” script or feature for brand new visitors.
- Short-lived promotions where you don’t want to redesign your entire header.
- Important notices (e.g., “We just shipped a big update”) that shouldn’t nag regulars.
It’s less suited for time-critical alerts that must be seen on every single visit, or for legal messages that require explicit acknowledgement. Those usually need a different UX and sometimes a proper consent log.
Accessibility and UX notes
The bar uses a close button with an aria-label so screen readers can announce
what it does. You can extend this by:
- Adding more descriptive text to the message so it stands on its own.
- Ensuring the contrast between background and text passes accessibility guidelines.
- Keeping the announcement short so it doesn’t cover too much of the viewport.
Because the bar appears at the top and can be dismissed permanently, it stays relatively polite compared to heavy-handed modals or full-screen overlays, while still being visible enough for new visitors to notice.
If you ever decide you don’t want the behavior anymore, you can remove the HTML, CSS,
and script block from your layout and any existing localStorage keys will
simply become unused data in the browser.
Comments (0)
No comments yet — be the first.