Visitor greeting custom element

to run in your site's root directory

View template source
create_file "app/javascript/components/visitor_greeting.js", <<~JS
  class VisitorGreeting extends HTMLElement {
    connectedCallback() {
      const referer = document.referrer.toLowerCase();
      const urlParams = new URLSearchParams(window.location.search);
      const refParam = urlParams.get("ref")?.toLowerCase();
      const source = refParam || referer;

      const templates = this.querySelectorAll("template[for]");

      for (const template of templates) {
        const key = template.getAttribute("for").toLowerCase();

        if (source.includes(key)) {
          this.innerHTML = template.innerHTML;

          return;
        }
      }
    }
  }

  customElements.define("visitor-greeting", VisitorGreeting);
JS

create_file "app/javascript/components/index.js", <<~JS, skip: true
import "./visitor_greeting"
JS

application_js_path = "app/javascript/application.js"

if File.exist?(application_js_path)
  insert_into_file application_js_path, "\nimport \"components\"\n", after: /\A(?:import .+\n)*/
else
  create_file application_js_path, <<~JS
import "components"
JS
end

unless File.exist?("config/importmap.rb")
  say "Warning: importmap.rb not found!", :yellow
  say "Please set up importmap-rails first by running:"
  say "  rails importmap:install"
  say "Or use your preferred JavaScript setup."

  return
end

insert_into_file "config/importmap.rb", after: /\A.*pin .+\n+/m do
  "\npin_all_from \"app/javascript/components\", under: \"components\", to: \"components\"\n"
end

def run_bundle; end

This custom element displays personalized messages to visitors based on where they came from. It checks both the HTTP referrer and the ref URL parameter.

Usage

Add the custom element to your page and define templates for different sources:

<visitor-greeting>
  <template for="producthunt">๐Ÿ‘‹ Hello Product Hunter!</template>
  <template for="news.ycombinator">๐Ÿงก Welcome Hacker News reader!</template>
  <template for="reddit">๐Ÿค– Hey Redditor!</template>
</visitor-greeting>

The element will:

  1. Check the ref URL parameter first (e.g., ?ref=producthunt)
  2. Fall back to the HTTP referrer header
  3. Match against the for attribute using substring matching
  4. Display the first matching template's content

Customization

You can use any HTML in your templates:

<visitor-greeting>
  <template for="producthunt">
    <h2>Welcome Product Hunters! ๐Ÿ˜ป</h2>

    <p>Special offer: 20% off with code HUNT20</p>
  </template>
</visitor-greeting>

Style the element with CSS to make it a banner, dialog, or anything else you need.