Back to Blog
Creating Tours 17. února 2025 8 min read

Why Dynamic Element IDs Can't Stop Your Product Tours

Patrik Duch

Founder, Illumate UI

Why Dynamic Element IDs Can't Stop Your Product Tours

Why Dynamic Element IDs Can't Stop Your Product Tours

You've built the perfect product tour. Every step highlights the right element, the fill action types in the email, the spotlight guides the user's eye. Then the website deploys an update and every element ID changes. Your tour breaks instantly.

This is the reality of dynamic element IDs — and most tour builders have no answer for it.

The Problem: GUIDs Everywhere

Modern web frameworks generate unique IDs for elements on every page load. Instead of a simple id="email-input", you get something like:

`
id="field-a3f8c2e1-9b4d-4e7a-b5c6-d8f2a1e3b4c5"
`

This GUID changes every time the page renders. Any tour builder that relies on auto-detected IDs will break immediately.

Why Sites Use Dynamic IDs

Framework-generated (React, Angular, Vue emit unique keys)

Anti-scraping protection

Anti-automation measures

A/B testing frameworks injecting dynamic attributes

CSS-in-JS libraries generating unique class names

The Solution: Custom CSS Selectors

Instead of relying on brittle auto-generated IDs, use stable attributes that don't change between deployments.

Selector Strategies That Work

By element type:

  • input — targets any input on the page

  • input[type="email"] — targets email inputs specifically

  • textarea — targets text areas
  • By name attribute:

  • input[name="email"] — form field names rarely change

  • input[name="password"] — same for password fields

  • select[name="country"] — dropdowns too
  • By class (stable ones):

  • .form-field input — structural classes tend to be stable

  • .login-form .email-input — component-level classes

  • .hs-error-msg — framework-specific classes (like HubSpot)
  • By position and structure:

  • form > div:nth-child(2) input — DOM structure is usually stable

  • .signup-form input:first-of-type — relative positioning
  • By placeholder or label:

  • input[placeholder="Enter your work email*"] — content-based targeting

  • label + input — structural relationship with labels
  • Selectors to Avoid

    Anything with a GUID: #field-a3f8c2e1-...

    Auto-generated class names: .css-1a2b3c, .sc-bdnxRM

    Framework internal attributes: [data-reactid="..."]

    Deeply nested positional selectors: body > div > div > div > ... > input

    Real-World Example

    A construction accounting website uses HubSpot forms with dynamic IDs on their newsletter signup. The email input renders as:

    `html

    `

    What breaks:


    #field-a3f8c2e1-random-guid — changes every page load.

    What works:


  • input — simple, reliable

  • input[type="email"] — specific enough

  • .hs-input — HubSpot's stable class

  • input[placeholder="Enter your work email*"] — content-based
  • In Illumate UI, you set the custom selector in the Input Selector field and your tour works regardless of ID changes.

    Combining with Other Features

    Custom selectors become even more powerful when combined with Illumate UI's other capabilities:

    Fill Action + Custom Selector


    Target the real input element, not the dynamic wrapper

    Animate typing for realistic demonstrations

    Persist filled values across tour steps

    Conditional Steps + Custom Selector


    Use stable selectors for error messages (.hs-error-msg)

    Add text matching for specific validation errors

    Skip steps gracefully when elements aren't present

    Cross-Page Tours + Custom Selector


    Same selector strategy works across different pages

    No need to update selectors after site deployments

    Tours survive framework updates and redesigns

    Testing Your Selectors

    Before saving your tour step, verify your selector works:

    1. Open the target website in your browser
    2. Press F12 to open DevTools
    3. In the Console tab, type: document.querySelector('your-selector')
    4. If it returns the element — your selector is solid
    5. Refresh the page and try again — if it still works, it's deployment-proof

    Quick Validation Checklist

    Does the selector work after a page refresh?

    Does it target exactly ONE element (or the right one)?

    Does it avoid any random-looking strings (GUIDs, hashes)?

    Would it survive a CSS framework update?

    Is it short and readable?

    How Enterprise Tools Handle This

    | Approach | Reliability | Illumate UI |
    |---|---|---|
    | Auto-detected IDs | Low — breaks with dynamic IDs | Not dependent on this |
    | SDK with data attributes | Medium — requires code access | Not needed |
    | Custom CSS selectors | High — targets stable attributes | Full support |
    | AI-powered element detection | Medium — can misidentify | Not needed |
    | XPath expressions | High but brittle | CSS selectors are simpler |

    Most enterprise tour builders auto-detect element IDs and call it a day. When those IDs are dynamic, they offer "AI-powered element detection" as a premium feature. Illumate UI gives you direct control with custom selectors — simpler, more reliable, and included in every plan.

    Best Practices

    Always prefer name, type, and semantic class attributes over IDs

    Test selectors across page refreshes before saving

    Use the simplest selector that uniquely identifies your target

    Document your selector strategy for team members

    Combine with conditional steps for maximum resilience

    When in doubt, input[type="email"] beats #dynamic-guid-123 every time

    The Bottom Line

    Dynamic element IDs are a solved problem. You don't need AI detection, you don't need SDK access, and you don't need to beg the website's dev team for stable IDs. You just need the right CSS selector.

    ---

    Build tours that survive any website update. Try Illumate UI — custom selectors, zero install, works on any website.

    Ready to improve your user onboarding?

    Start creating interactive product tours in minutes.