> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mention-me.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conversion Message Tag

> Display a reward reminder banner to referred friends and incented customers on your website

export const SignInNotice = ({message = "To see code snippets pre-filled with your partner code"}) => {
  return <div data-mm-sign-in style={{
    display: "none"
  }}>
      <Info>
        {message}, <a data-mm-sign-in-link href="https://app.mention-me.com/sign-in"><strong>sign in</strong></a>.
      </Info>
    </div>;
};

export const MerchantContext = () => {
  const PARTNER_STORAGE_KEY = "mm-docs-partner";
  const escapeHtml = str => str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
  const getStoredPartner = () => {
    try {
      const raw = localStorage.getItem(PARTNER_STORAGE_KEY);
      if (!raw) return null;
      const data = JSON.parse(raw);
      if (data && data.partnerCode) return data;
    } catch (e) {}
    return null;
  };
  const setStoredPartner = data => {
    try {
      localStorage.setItem(PARTNER_STORAGE_KEY, JSON.stringify(data));
    } catch (e) {}
  };
  const clearStoredPartner = () => {
    try {
      localStorage.removeItem(PARTNER_STORAGE_KEY);
    } catch (e) {}
  };
  const captureQueryParams = () => {
    const params = new URLSearchParams(window.location.search);
    const partner = params.get("partner");
    const name = params.get("name");
    if (partner) {
      const data = {
        partnerCode: partner
      };
      if (name) data.displayName = name;
      setStoredPartner(data);
      params.delete("partner");
      params.delete("name");
      const qs = params.toString();
      const clean = window.location.pathname + (qs ? "?" + qs : "") + window.location.hash;
      window.history.replaceState(null, "", clean);
      return data;
    }
    return getStoredPartner();
  };
  const isLocal = typeof window !== "undefined" && window.location.hostname === "localhost";
  const API_BASE = isLocal ? "http://localhost:3001" : "https://app.mention-me.com";
  const SIGN_IN_BASE = isLocal ? "http://localhost:3001/sign-in" : "https://app.mention-me.com/sign-in";
  const MERCHANT_WINDOW_KEY = "__mmMerchantContext";
  const publishMerchant = data => {
    window[MERCHANT_WINDOW_KEY] = data;
    window.dispatchEvent(new CustomEvent("mm-merchant-ready", {
      detail: data
    }));
  };
  const clearMerchant = () => {
    delete window[MERCHANT_WINDOW_KEY];
  };
  const BADGE_ID = "mm-partner-badge";
  const showPartnerBadge = (partnerData, source) => {
    if (document.getElementById(BADGE_ID)) return;
    const nav = document.getElementById("navigation-items");
    if (!nav || !nav.parentNode) return;
    const badge = document.createElement("div");
    badge.id = BADGE_ID;
    badge.className = "mm-partner-badge";
    const hasName = partnerData.displayName && partnerData.displayName !== partnerData.partnerCode;
    const heading = hasName ? escapeHtml(partnerData.displayName) : escapeHtml(partnerData.partnerCode);
    const code = hasName ? escapeHtml(partnerData.partnerCode) : "";
    const codeStr = code ? ' <span class="mm-partner-badge-code">' + code + '</span>' : '';
    const resetTitle = source === "clerk" ? "Sign out and switch account" : "Clear personalisation";
    badge.innerHTML = '<div class="mm-partner-badge-inner">' + '<span class="mm-partner-badge-content">' + '<span class="mm-partner-badge-context">Personalised for </span>' + '<span class="mm-partner-badge-name">' + heading + '</span>' + codeStr + '</span>' + '<button class="mm-partner-badge-reset" title="' + resetTitle + '">&times;</button>' + '</div>';
    nav.parentNode.insertBefore(badge, nav);
    badge.querySelector(".mm-partner-badge-reset").addEventListener("click", e => {
      e.preventDefault();
      e.stopPropagation();
      if (source === "clerk" && window.Clerk && window.Clerk.signOut) {
        clearMerchant();
        const redirect = SIGN_IN_BASE + "?redirect_url=" + encodeURIComponent(window.location.href);
        window.Clerk.signOut().then(() => {
          window.location.href = redirect;
        }).catch(() => {
          window.location.reload();
        });
        return;
      }
      clearStoredPartner();
      window.location.reload();
    });
  };
  const removePartnerBadge = () => {
    const el = document.getElementById(BADGE_ID);
    if (el) el.remove();
  };
  const showNotices = () => {
    document.querySelectorAll("[data-mm-sign-in]").forEach(el => {
      el.style.display = "";
    });
    const redirect = SIGN_IN_BASE + "?redirect_url=" + encodeURIComponent(window.location.href);
    document.querySelectorAll("[data-mm-sign-in-link]").forEach(a => {
      a.href = redirect;
    });
  };
  const hideNotices = () => {
    document.querySelectorAll("[data-mm-sign-in]").forEach(el => {
      el.style.display = "none";
    });
  };
  const walkCodeBlocks = replacements => {
    document.querySelectorAll("pre code").forEach(codeEl => {
      let html = codeEl.innerHTML;
      if (replacements) {
        for (const [from, to] of replacements) {
          html = html.split(from).join(escapeHtml(to));
        }
      }
      const paramStyle = "color:inherit;filter:brightness(110%);font-weight:bold;text-decoration:underline;cursor:pointer";
      html = html.replace(/(\?|&amp;)([a-z_]+)=/g, (match, prefix, name) => {
        const slug = name.replace(/_/g, "-");
        const target = document.getElementById("param-" + slug);
        if (!target) return match;
        return prefix + '<a href="#param-' + slug + '" style="' + paramStyle + '">' + name + "</a>=";
      });
      codeEl.innerHTML = html;
    });
  };
  const observeTabSwitches = callback => {
    let processing = false;
    const observer = new MutationObserver(() => {
      if (processing) return;
      processing = true;
      setTimeout(() => {
        callback();
        processing = false;
      }, 50);
    });
    setTimeout(() => {
      const tabs = document.querySelector("[role='tablist']");
      if (tabs && tabs.parentElement) {
        observer.observe(tabs.parentElement, {
          attributes: true,
          subtree: true,
          childList: true
        });
      }
    }, 500);
  };
  const pollForClerk = (onReady, onTimeout) => {
    let n = 0;
    const tick = () => {
      if (window.Clerk && window.Clerk.loaded) {
        return onReady(window.Clerk);
      }
      if (++n < 40) {
        setTimeout(tick, 250);
      } else {
        onTimeout();
      }
    };
    setTimeout(tick, 100);
  };
  const fetchMerchantFromAPI = () => {
    return fetch(API_BASE + "/api/docs/context", {
      credentials: "include",
      cache: "no-store"
    }).then(res => res.ok ? res.json() : null);
  };
  useEffect(() => {
    let cancelled = false;
    const urlPartner = captureQueryParams();
    const onPersonalised = (merchant, source) => {
      if (cancelled) return;
      const replacements = [["YOUR_PARTNER_CODE", merchant.partnerCode]];
      if (merchant.displayName) {
        replacements.push(["YOUR_TRADING_NAME", merchant.displayName]);
      }
      hideNotices();
      showPartnerBadge(merchant, source);
      walkCodeBlocks(replacements);
      observeTabSwitches(() => walkCodeBlocks(replacements));
    };
    const onUnauth = () => {
      if (cancelled) return;
      clearMerchant();
      removePartnerBadge();
      showNotices();
      walkCodeBlocks(null);
      observeTabSwitches(() => walkCodeBlocks(null));
    };
    const tryUrlFallback = () => {
      if (cancelled) return;
      if (urlPartner) {
        onPersonalised(urlPartner, "url");
      } else {
        onUnauth();
      }
    };
    if (!document.cookie.includes("__client_uat")) {
      tryUrlFallback();
      return;
    }
    pollForClerk(clerk => {
      if (cancelled) return;
      if (!clerk.session) {
        tryUrlFallback();
        return;
      }
      fetchMerchantFromAPI().then(data => {
        if (data) {
          publishMerchant(data);
          onPersonalised(data, "clerk");
        } else {
          tryUrlFallback();
        }
      }).catch(() => tryUrlFallback());
    }, () => {
      if (!cancelled) tryUrlFallback();
    });
    return () => {
      cancelled = true;
    };
  }, []);
  return null;
};

<MerchantContext />

## What is the conversion message used for?

The conversion message embeds a banner on pages of your website (generally the homepage and/or product pages) which is only shown in these cases:

<CardGroup cols={1}>
  <Card title="Mention Me Refer" icon="gift">
    Shown to referred friends that have a reward but have not purchased yet. The
    purpose of the message is to remind them of their reward and encourage them
    to go on to purchase.
  </Card>

  <Card title="Mention Me Retain" icon="rotate">
    Shown to customers who have been given an incentive to take an action. The
    purpose of the message is to remind incented customers of their reward and
    encourage them to take action.
  </Card>
</CardGroup>

## How to integrate the conversion message

<Steps>
  <Step title="Add the wrapper div">
    Include the following `<div>` into your page where you want the content to appear.

    ```html theme={null}
    <!-- Begin Mention Me conversion message placeholder div -->
    <div id="mmWrapper"></div>
    <!-- End Mention Me conversion message placeholder div -->
    ```
  </Step>

  <Step title="Add the JavaScript tag">
    Include the following JavaScript snippet at the bottom of the `<body>` tag on a landing page or information page. The request includes your unique partner code.

    <SignInNotice />

    <CodeGroup>
      ```html Demo theme={null}
      <!-- Begin Mention Me conversion message integration -->
      <script
        type="text/javascript"
        src="https://tag-demo.mention-me.com/api/v2/conversionmessage/YOUR_PARTNER_CODE?situation=homepage&locale=en_GB"
      ></script>
      <!-- End Mention Me conversion message integration -->
      ```

      ```html Live theme={null}
      <!-- Begin Mention Me conversion message integration -->
      <script
        type="text/javascript"
        src="https://tag.mention-me.com/api/v2/conversionmessage/YOUR_PARTNER_CODE?situation=homepage&locale=en_GB"
      ></script>
      <!-- End Mention Me conversion message integration -->
      ```
    </CodeGroup>
  </Step>

  <Step title="Customise the parameters">
    (Optional) Include data parameters passing the customer's details if you have them at the point in the process where you insert the tag — this makes the process smoother for the customer.

    <Snippet file="url-encoding-info.mdx" />
  </Step>
</Steps>

## Mandatory data parameters

<ResponseField name="situation" type="string" required>
  String indicator of where you are including this tag within your site (for
  example: `homepage`). Used for reporting. Has a maximum of 50 characters.
  Example: `homepage`
</ResponseField>

<ResponseField name="locale" type="string" required>
  String representing the required locale for the campaign. Used to show the
  right locale (language, currency) for the user. The format should be [ISO
  639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code,
  an underscore (`_`), then the [ISO 3166-1
  alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes) country code
  (e.g. `fr_FR` for French/France). Default is empty (which will result in a
  locale of `en_GB` being assumed). Example: `en_GB`
</ResponseField>

<Accordion title="Optional data parameters">
  <ResponseField name="firstname" type="string">
    The customer's firstname. Please URL encode.
  </ResponseField>

  <ResponseField name="surname" type="string">
    The customer's surname. Please URL encode.
  </ResponseField>

  <ResponseField name="fullname" type="string">
    The customer's full name. Please URL encode.
  </ResponseField>

  <ResponseField name="email" type="string">
    The customer's email address. Please URL encode.
  </ResponseField>

  <ResponseField name="customer_id" type="string">
    The unique customer identifier from your system.
  </ResponseField>

  <ResponseField name="phone_number" type="string">
    The customer's phone number(s). Pass as many phone numbers as you have as a
    comma-separated list. If you are passing any data which is not a digit (e.g.
    spaces, +'s), these need to be URL encoded.
  </ResponseField>

  <ResponseField name="call_to_action_url" type="string">
    A URL to send users to after they are rewarded. Only functions on the embedded
    flow.
  </ResponseField>

  <ResponseField name="segment" type="string">
    String representing a customer segment (for example one of: men, women) used
    to pass segmentation data about your customer to us. Has a maximum of 50
    characters.
  </ResponseField>
</Accordion>

<Accordion title="Optional implementation parameters">
  <ResponseField name="implementation" type="string">
    Optionally override the way the flow is implemented (one of: `link`, `form`,
    `embed`). Default can also be set in the merchant dashboard. If in doubt,
    leave out.
  </ResponseField>
</Accordion>
