1. The "two Identity Management register page templates" question
Most accounts have two Identity Management register page templates in the dashboard. Both are system-generated; do not delete either. They serve slightly different purposes:
-
Identity Management → Identity Management register page — the default, standard, longer-lived template. Use this for text edits and most modifications.
-
Experience > Identity Management → Identity Management register page — supports variants and can be invoked with a specific
templateIdfrom JavaScript. Use this when you need multiple visual variants or per-experience templates.
If a text change doesn't show up, you are almost certainly editing the template that isn't being rendered. Switch to the other one and re-apply.
The same advice applies to Identity Management login page — multiple system-generated copies may exist.
2. Customizing system templates — clone or use the registration event
Piano's system templates (register page, layout, etc.) are locked against custom Handlebars variables like {{params.url}} — you cannot inject your own template variables into them. Two ways to add custom logic anyway:
Clone the template
Manage → Templates → Add Template, choose the Registration use case, paste in modified HTML/CSS, and use the cloned template instead of the system one. Invoke it from a Composer Show Template card or from code:
tp.template.show({ templateId: '<template_id>' });
Note: CSS for system templates lives in the separate Identity Management Layout template, not in the register page template itself.
Use the Registration Success event
For post-registration logic (for example, redirecting users back to their origin page), listen to the Registration Success event in your Composer Integration Script. This event fires after a successful registration and exposes the user data — no template clone needed.
3. Changing the default input focus
By default, the Email field gets focus when the registration (or login) modal opens, forcing users to click back up if they need to start at First Name. To change the default focus:
-
Open the Identity Management register page (or Identity Management login page) template's HTML.
-
Find the input that currently has the
pn-autofocusattribute (or the legacyautofocus). -
Remove that attribute from the email input.
-
Add
pn-autofocusto the first-name input (or whichever input you want to receive focus first).
pn-autofocus is Piano's directive — use this rather than plain HTML autofocus, which can trigger a "Blocked autofocusing on a element in a cross-origin subframe" console error in Chrome (see the input-fields article for that specific fix).
4. Editing text on the registration modal
To change visible text inside the registration modal:
-
Piano dashboard → Settings → Translations.
-
Pick the locale you want to edit (English, Slovak, etc.).
-
Search by the current translation or by the English source key (for example, "Sign up" or "Register").
-
Edit and save.
Allow a few minutes for propagation; clear browser cache or use an incognito window to verify.
If the text still doesn't match after the change, check whether the Identity Management Layout template's CSS is applying text-transform: uppercase (or capitalize) and overriding your literal text. Remove the CSS rule that auto-capitalizes if you need exact casing.
5. Customizing the registration modal — "Register / Login" headline for checkout only
To show a specific message (for example, Register / Login) only when the registration modal is opened in a particular context, use the showIfInsideCheckout / hideIfInsideCheckout template directives, or a custom script that inspects the URL for an offer ID.
Conditional display during checkout
In the Identity Management register page template:
<header>
<div class="pane" showIfInsideCheckout>
<p class="register-login-msg">Register / Login</p>
</div>
</header>
The pane renders only when the user reaches the registration screen as part of a checkout flow.
Conditional display for a specific offer
When the trigger is an Offer ID rather than the generic checkout context, use a that inspects the URL:
<p id="regLoginMsg" style="display:none;">Register / Login</p>
<custom-script>
setTimeout(function() {
var url = (window.location != window.parent.location)
? document.referrer
: document.location.href;
if (url.indexOf('<Offer_ID>') !== -1) {
document.getElementById('regLoginMsg').style.display = 'block';
}
}, 1000);
</custom-script>
Replace with the actual offer identifier. The script handles the cross-origin iframe case via the window.location != window.parent.location check.
Test on staging or production (not in dashboard preview) — preview doesn't run the full user flow, so the script may not execute as expected.
6. Showing an extra message for a registration-term offer
A more general pattern for conditional in-template messaging: show an extra paragraph only when a user converts through an offer that contains a registration term.
Setup
-
Create a Composer experience targeting your pages / users with an offer containing the registration term.
-
Add this snippet to the end of the Identity Management register page template:
<custom-script>
setTimeout(function() {
var url = (window.location != window.parent.location)
? document.referrer
: document.location.href;
var index = url.indexOf('<offer_ID>');
var myDiv = document.getElementById('<id_of_element>');
if (index != -1) {
myDiv.style.display = "block";
}
if (index == -1) {
myDiv.style.display = "none";
}
}, 1000);
</custom-script>
-
Place the hidden element in the same template:
<p id="showonlyforspecificoffer" style="display:none;"> Specific text for your offer OF90BELNRHV4 </p>
Replace with your actual offer ID (e.g., OF90BELNRHV4) and with the matching element ID (showonlyforspecificoffer in the example). The paragraph appears only when the user comes via that specific registration offer.
7. Customizing for paid vs. free vs. checkout-driven registration
When you need different registration treatments depending on whether the user is signing up for a paid subscription, a free account, or via a checkout flow:
-
Template selection — use the standard Identity Management register page for the initial registration step, and the DOI / email-confirmation templates (covered in Cluster 01) for the confirmation step.
-
Conditional display via
showIfInsideCheckout/hideIfInsideCheckout— wrap context-specific elements (for example, "Why do we ask for this?" copy) in these directives so they appear only inside the checkout flow, not in standalone registration. -
Programmatic template selection — when invoking from JavaScript, pass
screen,templateId, andformNametotp.pianoId.show()to control which template / form pair renders for each flow type.
Inside-checkout messaging — the canonical example
<div class="checkout-help" showIfInsideCheckout> <h2>Why do I have to register?</h2> <p>We create your account so you can manage your subscription, save payment details, and access premium content on every device.</p> </div>
"Checkout Authentication in Separate State" — a config setting that changes behavior
In Business settings, the Checkout Authentication in Separate State toggle changes how registration and checkout screens are rendered:
-
Enabled — registration and checkout are shown as separate screens. The first screen counts as "inside checkout".
-
Disabled — registration / login and payment fields share one screen. The whole view counts as "inside checkout".
This setting affects which elements showIfInsideCheckout / hideIfInsideCheckout show or hide.
postMessage origin errors
If you see a console error like:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided does not match the recipient window's origin
…verify that your JavaScript Origins configuration uses https:// (not http://). Mismatched protocol is the typical cause.
8. Stage directives — *showIfStage / *hideIfStage
Identity Management supports only one register page template at a time. The templateId parameter in tp.pianoId.show() is ignored for the register screen if combined with formName — you cannot use it to swap in a different template for some flows.
To conditionally show / hide elements on the register page (extra fields, custom text, alternate submit buttons) based on the calling context, use the *showIfStage and *hideIfStage template display directives, plus the stage parameter on tp.pianoId.show().
Example
Annotate elements in the Identity Management register page template:
html
Sign up for our newsletter
Pass stage at runtime:
javascript tp.pianoId.show({ screen: 'register', displayMode: 'inline', formName: 'your-form-name', stage: 'newsletter', containerSelector: '#your-container-selector' });
Use formName to bind the form's custom fields and validation rules.
Combining formName (which controls fields) with stage (which controls template conditional rendering) gives you context-specific registration variants without multiple register-page templates.
9. Adding a registration link to the login template
The default Identity Management login template includes a "Don't have an account? Create one" link. If it's missing from yours (because of a customization that removed it), restore it either by resetting the template to default or by adding the HTML snippet manually:
<p class="register-link">
<t>Don't have an account?</t>
<a class="link"
data-e2e="noAccountPianoIDLink"
showScreen="register">
Create one
</a>
</p>
The showScreen="register" attribute is what tells Identity Management to close the login form and open the registration form when the link is clicked.
Save / publish, test in sandbox, then deploy. If you are using Global Mode, make sure the element appears only in the Identity Management Layout template — duplicating it in the login or register templates causes rendering issues.
10. Login vs. registration — separate templates
A single custom register/login template only overrides the registration flow. When you call:
tp.pianoId.show({ screen: 'register' }); // your custom template renders
tp.pianoId.show({ screen: 'login' }); // the system default login template renders
To customize the login view, you must edit the default Identity Management login page template directly in the dashboard — there is no "custom login template" to plug in from tp.pianoId.show({templateId}).
11. Styling the register page — Layout-level CSS
All styling for the register page lives in the Identity Management Layout template's CSS tab — the register page itself doesn't expose a CSS tab. To differentiate styling by how the modal was opened (from a checkout vs. from tp.pianoId.show() directly), use the two classes the Identity Management iframe wrapper applies:
|
Class |
When applied |
|---|---|
|
|
Template opened from checkout (inline rendering inside the checkout flow) |
|
|
Template opened directly via |
Example — color the registration text differently in each context:
.piano-id-inline { color: red; }
.piano-id-modal { color: green; }
12. Fixing layout issues
Email field stretched too wide on the register page
If the email field on the register page renders much wider than intended (and the login page is unaffected), the cause is usually CSS inheritance — screen-register is inheriting a width from body. Two fixes:
-
Add a width constraint to the body element in the Layout CSS:
css body { width: 50% !important; }
-
If needed, center the content with additional CSS on
html/body.
Verify in sandbox / staging across environments before promoting. If the issue persists, look for other CSS files or extensions that may be applying a width rule to body.
Removing the horizontal divider line at the top of the register page
The horizontal line that appears under the register page header can be removed via CSS or HTML.
CSS method — works for both embedded and modal display
Add to Manage → Templates → Identity Management Layout CSS tab:
/* Remove lines for both embedded and modal displays */
.account-popup-header,
#piano-id-container header,
header {
border-bottom: none !important;
box-shadow: none !important;
}
.divider,
[pn-divider],
divider {
display: none !important;
}
/* Remove line only for embedded display, keep for modal */
body:not(.tp-modal) .account-popup-header {
border-bottom: none !important;
}
HTML method — remove the element
-
Duplicate the Register template and open the Code tab.
-
Find (or any element with
class="divider") under the and remove it.
Test in sandbox / staging first.
13. Troubleshooting registration template errors
When the dashboard or browser console raises errors about the register page template, look first for unintended characters or syntax that the template renderer can misinterpret. A common culprit is stray asterisks (*) used outside of *showIfStage / *hideIfStage — the renderer may treat them as comment markers, producing errors like a missing setAttribute method on null. Remove the stray characters to clear the error.
For other failures:
-
Changes not appearing in QA / testing — verify the correct template is triggered, that no conflicting Composer experience is in the path, and that IP targeting / sandbox settings match the testing environment.
-
Strip unnecessary directives — directives left over from prior experiments can prevent the template from rendering as expected.