Skip to content

Data Attributes System

Overview

Balancy automatically processes HTML elements with special data attributes, providing declarative functionality without writing JavaScript code. This system allows you to configure UI behavior directly in HTML.

Key Benefits:

  • No JavaScript required for common patterns
  • Visual editors can configure behavior
  • Automatic backend integration
  • Type-safe data binding

Button Actions

Add data-button-action to make any element interactive and connected to Balancy backend.

Basic Usage

<!-- Buy offer button -->
<button data-button-action="101" data-button-params='{"productId": "coin_pack_1"}'>
  Buy Coins
</button>

<!-- Buy group offer -->
<button data-button-action="102" data-index="0">
  Buy Special Pack
</button>

<!-- Claim battle pass reward -->
<button data-button-action="104" data-index="2">
  Claim Reward
</button>

<!-- Close window -->
<button data-button-action="200">
  Close
</button>

Available Attributes

Attribute Type Description
data-button-action number Action ID from balancy.RequestAction enum
data-button-params JSON string Additional parameters for the action
data-index number Index parameter for array-based actions

Common Actions

Action ID Name Parameters Description
101 BuyOffer productId Purchase an offer
102 BuyGroupOffer index Purchase from group offer
103 BuyShopSlot slotId Purchase shop slot
104 BattlePassClaim lineId, index Claim battle pass reward
200 CloseWindow - Close the view

Button Events

Buttons dispatch events when actions complete:

balancyButtonResponse Event:

button.addEventListener('balancyButtonResponse', (event) => {
  const { actionId, result, success, senderId } = event.detail;

  if (success) {
    console.log(`Action ${actionId} succeeded:`, result);
    // Show success message
  } else {
    console.log(`Action ${actionId} failed:`, event.detail.error);
    // Show error message
  }
});

balancyButtonError Event:

button.addEventListener('balancyButtonError', (event) => {
  const { actionId, error, paramsAttr } = event.detail;
  console.error(`Button error: ${error}`);
});

Example: Purchase Flow

<!-- Button with custom styling and action -->
<button id="buy-btn"
        class="buy-button"
        data-button-action="101"
        data-button-params='{"productId": "starter_pack"}'>
  Buy Starter Pack
</button>

<script>
const buyBtn = document.getElementById('buy-btn');

buyBtn.addEventListener('balancyButtonResponse', (event) => {
  if (event.detail.success) {
    showSuccessAnimation();
    updatePlayerCurrency();
  } else {
    showErrorDialog(event.detail.error);
  }
});
</script>

Dynamic Text Updates

Elements with data-text-type="dynamic" automatically update with backend data.

Basic Dynamic Text

<!-- Show offer price -->
<span data-text-type="dynamic"
      data-info-type="1"
      data-text-format="{price} USD">
</span>

<!-- Show time remaining -->
<span data-text-type="dynamic"
      data-info-type="3"
      data-text-format="Time left: {time}">
</span>

Available Attributes

Attribute Type Description
data-text-type "dynamic" Marks element for dynamic updates
data-info-type number Type of information to fetch (InfoType enum)
data-text-format string Template string with {placeholder} syntax
data-custom string Custom parameter for InfoType.Custom
data-product-id string Product ID for price queries
data-index number Index for group offers

InfoType Values

Value Name Description Example
1 OfferPrice Display offer price "$4.99"
2 OfferGroupPrice Display group offer price "100 Gems"
3 TimeLeft Display time remaining (auto-formatted) "2h 15m"
4 OwnerLocalizedKey Format with owner data, use as localization key Localized text
5 OwnerCustom Format with owner data directly "25% OFF"
9 CustomPrice Display custom price Custom format
10 Custom Display custom data Any custom data

Advanced InfoTypes

OwnerLocalizedKey (InfoType 4)

Formats template using window.balancyViewOwner data, then uses result as a localization key.

When to use: Displaying localized text from backend data.

<!-- If owner has gameOffer.name = "OFFER_SUPER_PACK_NAME" -->
<span data-text-type="dynamic"
      data-info-type="4"
      data-text-format="{gameOffer.name}">
</span>
<!-- Displays: Localized text for key "OFFER_SUPER_PACK_NAME" -->

Automatic Document Resolution:

If gameOffer is null but unnyIdGameOffer exists: 1. System fetches document using balancy.getDocumentValue(unnyIdGameOffer) 2. Continues with path (name in this case) 3. Uses result as localization key

Owner Data Example:

window.balancyViewOwner = {
  instanceId: "f09ab140-3752-4593-98e3-48a31046",
  gameOffer: null,              // Will be auto-resolved
  unnyIdGameOffer: "1188",      // Used for resolution
  discount: 25,
  priceUSD: 4.99
};


OwnerCustom (InfoType 5)

Formats template using window.balancyViewOwner data directly for display.

When to use: Displaying raw values (numbers, custom strings, calculations).

<!-- Direct formatting with owner data -->
<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="{discount}% OFF - ${priceUSD}">
</span>
<!-- Displays: "25% OFF - $4.99" -->

Complex Formatting:

<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="Buy {quantity} for ${price} (Save {savings}%)">
</span>


Usage Guidelines

✓ Correct Pattern:

<!-- For localized title (use InfoType 4) -->
<h1 data-text-type="dynamic"
    data-info-type="4"
    data-text-format="{gameOffer.name}">
</h1>

<!-- For price and discount (use InfoType 5) -->
<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="{discount}% OFF">
</span>

<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="${priceUSD}">
</span>

✗ Incorrect Pattern:

<!-- DON'T do this - gameOffer.name is a localization key, not display text -->
<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="{gameOffer.name} - {discount}% OFF">
</span>

Key Points:

  • InfoType 4: Use when displaying localized text (e.g., gameOffer.name)
  • InfoType 5: Use for raw data (numbers, prices, custom strings)
  • Don't mix: Avoid combining localization keys with raw data in InfoType 5

Automatic Localization

Elements with data-text-type="localized" automatically get localized from the Localization system.

<h1 data-text-type="localized" data-localization-key="welcome_title">
  Welcome
</h1>

<button data-text-type="localized" data-localization-key="buy_button">
  Buy Now
</button>

<p data-text-type="localized" data-localization-key="tutorial.step_1">
  Click here to start
</p>

Process: 1. Element is found with data-text-type="localized" 2. Localization key is read from data-localization-key 3. Text is fetched using balancy.getLocalizedText(key) 4. Element's textContent is updated


Automatic Image Loading

Elements with data-image-id automatically load images from Balancy resources.

IMG Elements

<img data-image-id="icon_123" alt="Reward Icon">
<img data-image-id="player_avatar" alt="Player">

Background Images

<div data-image-id="background_456" class="hero-section"></div>
<div data-image-id="panel_bg" class="panel"></div>

9-Slice Images

<div data-image-id="button_bg"
     data-use-nineslice="true"
     slice-top="20"
     slice-right="20"
     slice-bottom="20"
     slice-left="20">
</div>

Process: 1. Element is found with data-image-id 2. Image URL is fetched using balancy.getImageUrl(id) 3. For IMG elements: src is set 4. For other elements: background-image or border-image-source is set


Custom Font Injection

Elements with font data attributes automatically load custom fonts.

<div data-font-id="font_789"
     data-font-name="CustomFont"
     class="styled-text">
  This text uses a custom font
</div>

<h1 data-font-id="title_font"
    data-font-name="TitleFont">
  Game Title
</h1>

Attributes:

  • data-font-id: Font asset ID in Balancy
  • data-font-name: Font family name to use in CSS

Element Identification

Use data-id for JavaScript element queries (alternative to HTML id).

<div data-id="player-info">
  <span data-id="player-name">Player Name</span>
  <span data-id="player-level">Level 1</span>
  <img data-id="player-avatar" src="avatar.png">
</div>

JavaScript:

// Find by data-id
const playerInfo = balancy.findDomElement('player-info');
const nameElement = balancy.findDomElement('player-name', playerInfo);
const levelElement = balancy.findDomElement('player-level', playerInfo);

Benefits:

  • Namespace separation from HTML IDs
  • Easier to query within scopes
  • Framework convention

Prefab Placeholders

Use data-prefab-id to mark where prefabs should be instantiated.

<!-- Placeholder for player card prefab -->
<div data-prefab-id="player-card"
     data-guid="..."
     class="card-container">
</div>

<!-- Placeholder for shop prefab -->
<div data-prefab-id="shop"
     data-guid="...">
</div>

Process: 1. Placeholder found with data-prefab-id 2. Prefab loaded by ID 3. Prefab children moved to placeholder 4. data-prefab-id attribute removed (prevents reprocessing) 5. Nested prefabs processed recursively

Learn More: Prefabs & Components


Script Components

Use data-script-id to attach script components to elements (new component system).

<div id="health-bar">
  <div data-script-id="HealthBar"
       data-guid="abc123..."
       data-script-params='{"maxHealth":{"type":"number","value":100}}'
       style="display:none">
  </div>

  <div class="health-bar-fill"></div>
</div>

Attributes:

  • data-script-id: Script class name
  • data-guid: Unique identifier
  • data-script-params: Serialized parameters (JSON)
  • style="display:none": Hidden by default

Learn More: Prefabs & Components


Combining Attributes

You can combine multiple data attributes on a single element:

<button data-id="buy-button"
        data-button-action="101"
        data-button-params='{"productId": "gems_100"}'
        data-text-type="dynamic"
        data-info-type="1"
        data-text-format="Buy for {price}">
  Buy Gems
</button>

This button: - Has identifier buy-button for JavaScript queries - Triggers purchase action (101) - Displays dynamic price text - All configured declaratively in HTML!


Best Practices

1. Use Semantic Attributes

<!-- ✓ Good: Clear, semantic -->
<button data-button-action="101"
        data-button-params='{"productId": "starter_pack"}'>
  Buy Starter Pack
</button>

<!-- ✗ Avoid: Magic numbers without context -->
<button data-action="101" data-params='{"p": "sp"}'>
  Buy
</button>

2. Format JSON Correctly

<!-- ✓ Good: Valid JSON with double quotes -->
<div data-button-params='{"productId": "coins", "amount": 100}'></div>

<!-- ✗ Avoid: Invalid JSON -->
<div data-button-params="{productId: coins, amount: 100}"></div>

3. Use InfoType Appropriately

<!-- ✓ Good: InfoType 4 for localized keys -->
<h1 data-text-type="dynamic"
    data-info-type="4"
    data-text-format="{gameOffer.name}">
</h1>

<!-- ✓ Good: InfoType 5 for raw data -->
<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="${price}">
</span>

<!-- ✗ Avoid: Mixing in InfoType 5 -->
<span data-text-type="dynamic"
      data-info-type="5"
      data-text-format="{gameOffer.name} - ${price}">
</span>

4. Provide Fallback Content

<!-- ✓ Good: Fallback text before dynamic update -->
<span data-text-type="dynamic"
      data-info-type="3"
      data-text-format="Time left: {time}">
  Loading...
</span>

<!-- ✗ Avoid: Empty, causes layout shift -->
<span data-text-type="dynamic"
      data-info-type="3"
      data-text-format="Time left: {time}">
</span>

Troubleshooting

Dynamic Text Not Updating

Problem: Text element stays with fallback content.

Solutions:

  • Check data-info-type is valid number
  • Verify window.balancyViewOwner has required data
  • Look for JavaScript errors in console
  • Ensure data-text-format placeholders match data keys

Button Not Responding

Problem: Button click does nothing.

Solutions:

  • Verify data-button-action is valid action ID
  • Check data-button-params is valid JSON
  • Look for balancyButtonError events
  • Ensure button is not disabled

Images Not Loading

Problem: Image element shows broken icon or no image.

Solutions:

  • Verify image ID exists in Balancy assets
  • Check data-image-id attribute is correct
  • Look for 404 errors in Network tab
  • Ensure images are deployed

Fonts Not Applied

Problem: Custom font not showing.

Solutions:

  • Verify font is uploaded to Balancy
  • Check data-font-id and data-font-name match
  • Ensure font is added to view in UI Builder
  • Look for font loading errors in console

Next Steps