Affiliate Hydration Cheatsheet
A single storefront page is cached once and served to every visitor — attributed or anonymous. Affiliate-specific values (name, avatar, link URLs) are filled in on the client by the FairShare SDK. This page tells theme authors which variable to use in which context and how to avoid the traps.
The mental model
Under hydration:
- The rendered HTML is affiliate-independent. It contains placeholders (sentinels, custom elements, or data attributes) where affiliate values would go.
- The FairShare SDK runs on every page and swaps those placeholders with the resolved affiliate's values.
- Anonymous visitors (URL has no rep prefix) get the same HTML with fallback values (
"home"for URL segments, empty for text).
If you author a theme assuming affiliate values are baked into the HTML at render time, your theme will break under hydration. This page explains what changes.
The three mechanisms
| # | Mechanism | Use for | Example |
|---|---|---|---|
| 1 | Custom element — <fluid-affiliate-*> | Text content that displays an affiliate field | <span>Hi, <fluid-affiliate-name>friend</fluid-affiliate-name></span> |
| 2 | Data attribute — data-fluid-affiliate-* | An HTML attribute value (src, href, alt) that should hold an affiliate field | <img data-fluid-affiliate-src="avatar"> |
| 3 | Inline sentinel — {{ username }} | A rep username embedded inside a string (URL path segment, JSON attribute) | <a href="/{{ username }}/shop"> |
Each mechanism solves a case the others can't:
- A custom element can't live inside an attribute.
- A whole-attribute data marker would replace the entire value.
- The inline sentinel is safe only in attributes dereferenced on user interaction (
href,action), not eagerly-fetched ones (src).
Variable reference
Text fields — affiliate name, email, initials, avatar URL, my_site_url
Do not use these in template text or attributes; the raw value only exists on mysite renders.
Use the corresponding custom element:
| Field | Custom element | Fallback text |
|---|---|---|
| Name | <fluid-affiliate-name> | put default inside the tag |
<fluid-affiliate-email> | put default inside the tag | |
| Initials | <fluid-affiliate-initials> | put default inside the tag |
| Avatar URL | <fluid-affiliate-avatar> | put default inside the tag |
| MyHub URL | <fluid-affiliate-my-site-url> | put default inside the tag |
<p>Shop with <fluid-affiliate-name>our team</fluid-affiliate-name></p> <span class="badge"><fluid-affiliate-initials>FA</fluid-affiliate-initials></span>
The element lives in the light DOM (no Shadow DOM) so surrounding theme styles apply normally.
Attribute values — same fields, when used inside src, href, alt
Use a data marker on the host element:
| Attribute | Marker | Fills |
|---|---|---|
| Image source | data-fluid-affiliate-src="<field>" | src |
| Link href | data-fluid-affiliate-href="<field>" | href |
| Alt text | data-fluid-affiliate-alt="<field>" | alt |
| Any text | data-fluid-affiliate="<field>" | textContent (when a custom tag isn't usable) |
<field> is one of name, email, avatar, initials, my_site_url.
<img data-fluid-affiliate-src="avatar" data-fluid-affiliate-alt="name" /> <a data-fluid-affiliate-href="my_site_url">View store</a>
my_site_url normally resolves to <page-origin>/my/<username>. To point at a different origin (e.g. a preview environment or a whitelabelled domain), add data-fluid-affiliate-base-url on the same element:
<!-- Default: uses the current page's origin --> <a data-fluid-affiliate-href="my_site_url">View store</a> <!-- Explicit origin override --> <a data-fluid-affiliate-href="my_site_url" data-fluid-affiliate-base-url="https://staging.example.com" >View store</a>
The SDK resolves the affiliate's my_site_url against the supplied base URL instead of window.location.origin. Only affects my_site_url; other fields ignore this attribute.
URL path segments — {{ username }} and its siblings
For a rep username embedded inside a URL string, use the inline sentinel:
<a href="/{{ username }}/shop">Shop</a> <form action="/{{ username }}/join">...</form>
{{ username }} compiles to __fluid_affiliate_username__ under hydration. The SDK swaps every occurrence with the resolved rep username, falling back to "home" for anonymous visitors.
Other identifiers:
| Variable | Emits under hydration | Use for |
|---|---|---|
{{ username }} | Sentinel | Path segments in link/form URLs (e.g., /<username>/shop) |
{{ share_guid }} | Sentinel | Sharing-link surfaces where a stable identifier is needed |
{{ affiliate_guid }} | Sentinel | Legacy alias for share_guid |
{{ sharing_id }} | Sentinel | Sharing link variants where external IDs override the username |
{{ external_id }} | Real value | Backend-only surfaces (webhooks, non-cached contexts) |
Company URL helpers — company.shop_page_url, company.join_page_url
These already emit URLs with the sentinel baked in when hydration is on:
<a href="{{ company.shop_page_url }}">Shop</a> <!-- Renders to: <a href="/__fluid_affiliate_username__/shop">Shop</a> under hydration -->
No theme edit is needed. The SDK swaps the sentinel client-side.
Fields that stay real (no hydration)
| Variable | Value under hydration |
|---|---|
{{ affiliate.web_rep_store_enabled }} | Real (company-level setting, not per-rep) |
{{ affiliate.logged_in_rep_for_store }} | Real |
{{ affiliate.sign_in_url }} / sign_out_url | Real placeholders ("#") — use client-side JS to populate |
{{ company.* }} (except URL helpers above) | Real (not affiliate-dependent) |
Conditional visibility — the pattern that replaces {% if affiliate.X %}
Under hydration, {{ affiliate.name }} at render time is the placeholder — never blank. So:
<!-- ALWAYS true under hydration - broken --> <span>Hi, {{ affiliate.name }}</span>