Unity WebGL Integration

Integrate BZZE Ads into your Unity game exported to WebGL using JavaScript interop. Call the SDK from C# scripts.

✅ Perfect For: Unity WebGL exports (browser games)
⚠️ Note: This guide is for Unity WebGL exports only. For native mobile (iOS/Android), you'll need a different approach or wrapper SDK.

How It Works

Unity WebGL can communicate with JavaScript using:

  • Application.ExternalCall() - Call JavaScript from C#
  • Application.ExternalEval() - Execute JavaScript code
  • [DllImport("__Internal")] - Import JavaScript functions as C# methods

We'll use this to bridge Unity C# ↔ BZZE Ads JavaScript SDK.

Quick Setup

Step 1: Modify WebGL Template

After building your Unity WebGL project, edit the generated index.html:

index.html (add before closing </body>)
<!-- Load BZZE Ads SDK -->
<script src="https://ads.bzze.com/sdk/rewarded.min.js"></script>

<script>
// Initialize BZZE Ads after Unity loads
window.addEventListener('load', function() {
    setTimeout(function() {
        window.RewardedAd.init({
            appId: 'YOUR_APP_ID',
            apiKey: 'YOUR_API_KEY',
            userId: 'user_' + Date.now(),
            autoPreload: true,
            
            onReward: function(reward) {
                // Call Unity C# method
                if (typeof unityInstance !== 'undefined') {
                    unityInstance.SendMessage('BZZEAdsManager', 'OnAdRewardEarned', '');
                }
            },
            
            onAdLoaded: function(count) {
                if (typeof unityInstance !== 'undefined') {
                    unityInstance.SendMessage('BZZEAdsManager', 'OnAdsLoaded', count.toString());
                }
            },
            
            onNoFill: function() {
                if (typeof unityInstance !== 'undefined') {
                    unityInstance.SendMessage('BZZEAdsManager', 'OnNoFill', '');
                }
            },
            
            onError: function(error) {
                if (typeof unityInstance !== 'undefined') {
                    unityInstance.SendMessage('BZZEAdsManager', 'OnAdError', error.message);
                }
            }
        });
    }, 1000);
});

// Expose functions for Unity to call
window.ShowBZZEAd = function(rewardPreview, placement) {
    if (window.RewardedAd) {
        window.RewardedAd.showAd({
            rewardPreview: rewardPreview || '',
            placement: placement || 'default'
        });
    }
};

window.IsBZZEAdAvailable = function() {
    return window.RewardedAd ? window.RewardedAd.isAdAvailable() : false;
};
</script>

Step 2: Create C# Manager Script

Create Assets/Scripts/BZZEAdsManager.cs:

BZZEAdsManager.cs
using UnityEngine;
using System.Runtime.InteropServices;

public class BZZEAdsManager : MonoBehaviour
{
    // Events
    public delegate void AdRewardEarnedHandler();
    public static event AdRewardEarnedHandler OnRewardEarned;
    
    public delegate void AdsLoadedHandler(int count);
    public static event AdsLoadedHandler OnAdsAvailable;
    
    public delegate void NoFillHandler();
    public static event NoFillHandler OnAdNoFill;
    
    public delegate void ErrorHandler(string message);
    public static event ErrorHandler OnAdErrorOccurred;

    // Import JavaScript functions
    [DllImport("__Internal")]
    private static extern void ShowBZZEAd(string rewardPreview, string placement);
    
    [DllImport("__Internal")]
    private static extern bool IsBZZEAdAvailable();

    private static BZZEAdsManager instance;

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            gameObject.name = "BZZEAdsManager"; // Important: must match SendMessage name
        }
        else
        {
            Destroy(gameObject);
        }
    }

    // Call this from Unity to show an ad
    public static void ShowAd(string rewardPreview = "", string placement = "default")
    {
        #if UNITY_WEBGL && !UNITY_EDITOR
            ShowBZZEAd(rewardPreview, placement);
        #else
            Debug.Log("BZZE Ads: ShowAd() called (WebGL only)");
        #endif
    }

    // Check if ads are available
    public static bool IsAdAvailable()
    {
        #if UNITY_WEBGL && !UNITY_EDITOR
            return IsBZZEAdAvailable();
        #else
            return false;
        #endif
    }

    // Called from JavaScript when reward earned
    public void OnAdRewardEarned(string data)
    {
        Debug.Log("BZZE Ads: Reward earned!");
        OnRewardEarned?.Invoke();
    }

    // Called from JavaScript when ads loaded
    public void OnAdsLoaded(string countStr)
    {
        int count = int.Parse(countStr);
        Debug.Log($"BZZE Ads: {count} ads loaded");
        OnAdsAvailable?.Invoke(count);
    }

    // Called from JavaScript when no ads
    public void OnNoFill(string data)
    {
        Debug.Log("BZZE Ads: No ads available");
        OnAdNoFill?.Invoke();
    }

    // Called from JavaScript on error
    public void OnAdError(string message)
    {
        Debug.LogError($"BZZE Ads Error: {message}");
        OnAdErrorOccurred?.Invoke(message);
    }
}

Step 3: Create Plugin File (Optional but Recommended)

Create Assets/Plugins/BZZEAds.jslib:

BZZEAds.jslib
mergeInto(LibraryManager.library, {
    ShowBZZEAd: function(rewardPreviewPtr, placementPtr) {
        var rewardPreview = UTF8ToString(rewardPreviewPtr);
        var placement = UTF8ToString(placementPtr);
        
        if (window.ShowBZZEAd) {
            window.ShowBZZEAd(rewardPreview, placement);
        }
    },
    
    IsBZZEAdAvailable: function() {
        if (window.IsBZZEAdAvailable) {
            return window.IsBZZEAdAvailable() ? 1 : 0;
        }
        return 0;
    }
});

Step 4: Use in Your Game Scripts

GameManager.cs
using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
    public Text coinsText;
    public Button watchAdButton;
    
    private int coins = 0;

    void Start()
    {
        // Subscribe to ad events
        BZZEAdsManager.OnRewardEarned += HandleAdReward;
        BZZEAdsManager.OnAdsAvailable += HandleAdsLoaded;
        BZZEAdsManager.OnAdNoFill += HandleNoFill;
        
        // Set up button
        watchAdButton.onClick.AddListener(ShowRewardedAd);
        
        // Check ad availability every 2 seconds
        InvokeRepeating("UpdateAdButton", 0f, 2f);
        
        UpdateUI();
    }

    void OnDestroy()
    {
        // Unsubscribe
        BZZEAdsManager.OnRewardEarned -= HandleAdReward;
        BZZEAdsManager.OnAdsAvailable -= HandleAdsLoaded;
        BZZEAdsManager.OnAdNoFill -= HandleNoFill;
    }

    void ShowRewardedAd()
    {
        // Show ad
        BZZEAdsManager.ShowAd("100 coins", "main_menu");
    }

    void HandleAdReward()
    {
        // Grant reward
        coins += 100;
        UpdateUI();
        
        // Show success message
        Debug.Log("You earned 100 coins!");
    }

    void HandleAdsLoaded(int count)
    {
        Debug.Log($"{count} ads are ready");
    }

    void HandleNoFill()
    {
        Debug.Log("No ads available right now");
    }

    void UpdateAdButton()
    {
        watchAdButton.interactable = BZZEAdsManager.IsAdAvailable();
    }

    void UpdateUI()
    {
        coinsText.text = $"Coins: {coins}";
    }
}

Complete Example

Here's a full game manager with multiple reward types:

CompleteGameManager.cs
using UnityEngine;
using UnityEngine.UI;

public class CompleteGameManager : MonoBehaviour
{
    [Header("UI Elements")]
    public Text coinsText;
    public Text livesText;
    public Button watchAdForCoinsButton;
    public Button watchAdForLifeButton;
    
    [Header("Game State")]
    private int coins = 0;
    private int lives = 3;
    private string currentRewardType = "";

    void Start()
    {
        // Subscribe to events
        BZZEAdsManager.OnRewardEarned += OnAdRewardEarned;
        BZZEAdsManager.OnAdNoFill += OnAdNoFill;
        BZZEAdsManager.OnAdErrorOccurred += OnAdError;
        
        // Set up buttons
        watchAdForCoinsButton.onClick.AddListener(WatchAdForCoins);
        watchAdForLifeButton.onClick.AddListener(WatchAdForLife);
        
        // Update button states
        InvokeRepeating("UpdateButtonStates", 0f, 2f);
        
        UpdateUI();
    }

    void OnDestroy()
    {
        BZZEAdsManager.OnRewardEarned -= OnAdRewardEarned;
        BZZEAdsManager.OnAdNoFill -= OnAdNoFill;
        BZZEAdsManager.OnAdErrorOccurred -= OnAdError;
    }

    void WatchAdForCoins()
    {
        currentRewardType = "coins";
        BZZEAdsManager.ShowAd("100 coins", "menu_coins");
    }

    void WatchAdForLife()
    {
        currentRewardType = "life";
        BZZEAdsManager.ShowAd("1 extra life", "menu_life");
    }

    void OnAdRewardEarned()
    {
        switch (currentRewardType)
        {
            case "coins":
                coins += 100;
                ShowMessage("You earned 100 coins!");
                break;
            case "life":
                lives += 1;
                ShowMessage("You earned 1 extra life!");
                break;
        }
        
        currentRewardType = "";
        UpdateUI();
    }

    void OnAdNoFill()
    {
        ShowMessage("No ads available right now");
    }

    void OnAdError(string message)
    {
        ShowMessage($"Error: {message}");
    }

    void UpdateButtonStates()
    {
        bool adsAvailable = BZZEAdsManager.IsAdAvailable();
        watchAdForCoinsButton.interactable = adsAvailable;
        watchAdForLifeButton.interactable = adsAvailable;
    }

    void UpdateUI()
    {
        coinsText.text = $"💰 Coins: {coins}";
        livesText.text = $"❤️ Lives: {lives}";
    }

    void ShowMessage(string message)
    {
        Debug.Log(message);
        // Show UI message to player
    }

    // Call this when player dies
    public void OnGameOver()
    {
        // Show continue with ad option
        currentRewardType = "continue";
        // Show UI asking if player wants to watch ad to continue
    }
}

Best Practices

1. Use DontDestroyOnLoad

Keep BZZEAdsManager alive across scenes:

C#
void Awake()
{
    DontDestroyOnLoad(gameObject);
}

2. Pause Game During Ads

C#
void ShowAd()
{
    // Pause game
    Time.timeScale = 0;
    AudioListener.pause = true;
    
    // Show ad
    BZZEAdsManager.ShowAd("100 coins");
}

void OnAdRewardEarned()
{
    // Resume game
    Time.timeScale = 1;
    AudioListener.pause = false;
    
    // Grant reward
    GrantReward();
}

3. Test in Editor with Mocks

C#
public static void ShowAd(string rewardPreview = "", string placement = "default")
{
    #if UNITY_WEBGL && !UNITY_EDITOR
        ShowBZZEAd(rewardPreview, placement);
    #else
        // Mock behavior in editor
        Debug.Log($"[Mock] Showing ad: {rewardPreview}");
        if (instance != null)
        {
            instance.StartCoroutine(MockAdReward());
        }
    #endif
}

#if UNITY_EDITOR
private System.Collections.IEnumerator MockAdReward()
{
    yield return new WaitForSeconds(2f);
    OnRewardEarned?.Invoke();
}
#endif

Custom WebGL Template (Advanced)

To avoid editing index.html after every build:

  1. Copy Unity's default WebGL template from Unity/PlaybackEngines/WebGLSupport/BuildTools/WebGLTemplates/Default
  2. Paste into Assets/WebGLTemplates/BZZEAds
  3. Edit index.html in that folder to include BZZE Ads SDK
  4. In Unity: Player Settings → Resolution and Presentation → WebGL Template → BZZEAds

Now every build will include BZZE Ads automatically!

Troubleshooting

SendMessage not working

Problem: Unity doesn't receive JavaScript callbacks

Solution: Make sure GameObject name matches exactly: gameObject.name = "BZZEAdsManager";

DllImport error

Problem: DllNotFoundException: __Internal

Solution: This is expected in Editor. Wrap calls in #if UNITY_WEBGL && !UNITY_EDITOR

Ads not showing

Problem: No ads appear in WebGL build

Solution: Check browser console (F12) for errors. Make sure index.html was modified correctly.

Next Steps