# Ezoic Docs This file is generated automatically from the Hugo documentation tree for AI agents and large-context scanning. # Setup --- ## Preface Source: https://docs.ezoic.com/docs/ezoicads/getting-started/ This guide will walk you through setting up EzoicAds on your website in three simple steps. The process is straightforward and we're here to help every step of the way. ## Before You Start Here's what you'll need: 1. An Ezoic account - [Create one here](https://pubdash.ezoic.com/join) if you don't have one yet 2. The ability to edit your website's code (or someone who can help you) 3. Your Ezoic Onboarding Specialist is available to guide you through any part of this process Ready? Let's move on to Step 1: Integration. --- ## Step 1: Site Integration Source: https://docs.ezoic.com/docs/ezoicads/integration/ **WordPress Users:** If you're using WordPress, you can simplify this integration process by using our WordPress Plugin. The plugin handles all the setup steps automatically. [Learn more about the Ezoic WordPress Plugin integration guide](https://support.ezoic.com/kb/article/ezoic-wordpress-plugin-javascript-integration-guide). Ezoic's JavaScript integration provides a flexible, client-side solution for displaying ads on your website. This integration method gives you full control over ad execution and is compatible with all website builds and content management systems. The integration process involves two main components: 1. **Header Scripts** - Essential JavaScript files that initialize the Ezoic ad system 2. **Ad Placement Code** - JavaScript snippets that define where ads will appear on your pages This approach ensures optimal ad performance while maintaining your website's functionality and user experience. ## Add Header Scripts Add the **Ezoic Privacy Scripts** and **Header Script** at the very top of the `
` tag. Please ensure you load the privacy scripts before the header script. ### Privacy Scripts The privacy scripts handle user consent management and must be loaded first to ensure compliance with privacy regulations: ```html ``` The `data-cfasync="false"` attribute prevents Cloudflare from optimizing these scripts, ensuring they load in the correct order for privacy compliance. The attribute is required to be placed in front of the src attribute to work properly. ### Header Script The main Ezoic header script initializes the ad system on your website: ```html ``` ### Script Placement Guidelines For quicker ad setup and delivery, we recommend inserting these header scripts within the `` tag. If placing them in the head is not feasible, the next best option is to position them at the very top of the `` tag. **Best Practices:** - Load privacy scripts before the header script - Place all scripts as high as possible in the `` section - Avoid loading scripts conditionally or after page load - Ensure scripts are not blocked by ad blockers or CSP policies ### Verification Once you have completed adding these header scripts to your website, you have successfully completed the first step of EzoicAds integration. To verify everything is working correctly, visit your website and ensure it loads normally without any broken functionality. If you encounter any issues or need assistance, please reach out to Ezoic's support team. You're now ready to proceed to the next step: setting up your ads.txt file. --- ## Step 2: Ads.txt Setup Source: https://docs.ezoic.com/docs/ezoicads/adstxt/ Ads.txt setup is required for all publishers using Ezoic. This file helps maximize your ad revenue by ensuring authorized ad partners can bid on your inventory. ## What is Ads.txt? Ads.txt is a simple text file that tells advertisers which companies are authorized to sell ads on your website. Think of it as a "verified seller" list that prevents unauthorized companies from selling fake ad space on your domain. ## Choose Your Setup Method Select the method that best fits your website setup: **Important:** Replace `[YOUR_DOMAIN].com` with your actual domain name in all code examples below. ### 1. WordPress Sites (Recommended) **Easiest option for WordPress users:** 1. Install the [**Ezoic Integration Plugin**](https://wordpress.org/plugins/ezoic-integration/) from your WordPress admin dashboard 2. Activate the plugin and navigate to its settings 3. Enable the ads.txt management feature 4. The plugin handles everything automatically The Ezoic WordPress plugin automatically manages your ads.txt file and keeps it updated. No technical setup required! ### 2. Server Redirects **For users with server access:** **Apache (.htaccess):** ```apache Redirect 301 /ads.txt https://srv.adstxtmanager.com/19390/[YOUR_DOMAIN].com ``` **Nginx:** ```nginx server { location ~ /ads.txt { return 301 https://srv.adstxtmanager.com/19390/[YOUR_DOMAIN].com; } } ``` **PHP:** ```php ``` ### 3. Automated Updates (Advanced) **For automatic daily updates:** ```bash curl -L https://srv.adstxtmanager.com/19390/[YOUR_DOMAIN].com > ads.txt ``` Set up a daily cron job to run this command automatically and keep your ads.txt file current. ## Test Your Setup 1. **Visit** `yourdomain.com/ads.txt` in your browser 2. **Verify** you see a list of authorized ad sellers 3. **Clear your website cache** if the file doesn't appear immediately ## Complete! Once your ads.txt file is working correctly, you've successfully completed Step 2. Your website is now properly configured to work with Ezoic's advertising partners, helping maximize your ad revenue. Ready for the final step? Continue to **Step 3: Ad Placements** to start displaying ads on your website. --- ## Step 3: Ad Placements Source: https://docs.ezoic.com/docs/ezoicads/implementation/ Now that you've integrated Ezoic's scripts and set up your ads.txt file, it's time to add ad placements to your website. This final step will start displaying ads and generating revenue. ## Create Your Ad Placements First, you'll need to create ad placements in your Ezoic dashboard. These define where ads will appear on your website. You can create placements yourself in your [Ezoic Dashboard](https://pubdash.ezoic.com/ezoicads/adpositions/placeholders), or work with your Ezoic Onboarding Specialist for optimized placement recommendations. ## Add Placement Code to Your Website Once you have your ad placement IDs, add this code wherever you want ads to appear on your site: ```html ``` Replace `101` with your actual placement ID from the dashboard. Insert this code for each ad location on your site. Pages with multiple placements should pass all placement IDs into a single `showAds()` call. This reduces server requests and improves loading speed. _Example: `ezstandalone.showAds(101, 102, 103, 104)`_ DO NOT add any styling to the actual placeholder `div`. Adding styles or reserving space for the ad may result in empty white space if an ad doesn't load. Calling `ezstandalone.showAds()` without defining a placeholder value will call the function for every placeholder that exists on that page. **Important:** To ensure Ezoic ads work properly on your site, don't forget to remove any leftover ad code from other ad networks. ## Setup Complete Once you have completed these steps, you have successfully implemented EzoicAds on your site. If you have any questions or need assistance, please reach out to Ezoic's support team. --- ## Dynamic Content Source: https://docs.ezoic.com/docs/ezoicads/dynamic-content/ This section is for websites where content loads or changes dynamically. For example, a modal may appear when a user clicks a button, or the page may change without a full reload. ## Changing Pages When switching between pageviews dynamically, it is important to re-call `ezstandalone.showAds()` to force ads to refresh on the new URL. ```html ``` Calling this function with no values will automatically call every existing placeholder on the new page. It will also refresh the anchor and video ad locations. ## New Content For additional placeholders within the same pageview, you can use the `ezstandalone.showAds` function. If a user clicks a button, new content loads, and placeholders `104` and `105` are added, `ezstandalone.showAds` should be used to display them. ```html ``` ## Changing content If the content changes within the same pageview and a placeholder is no longer needed or visible, the placeholder needs to be properly cleaned up using `ezstandalone.destroyPlaceholders`. ```html ``` If this content becomes visible again, you can recall these locations using `ezstandalone.showAds`, such as in the "New Content" example above. ## Infinite Scroll For sites which implement an infinite scroll, it is recommended to use unique placeholder IDs on each subsequent article, which can be called using `ezstandalone.showAds` when the new article loads. For example, Article 1 may contain placeholders `102`, `103` and `104`, while Article 2 may contain placeholders `105` and `106`. When the first article loads: ```html ``` When the user scrolls to the second article, the next set of ads will be loaded using: ```html ``` It is recommended to create a set of `in-content` placeholders specifically for infinite scroll. If placeholder IDs are reused in the newly loaded articles, then `ezstandalone.destroyPlaceholders` must be used prior to `ezstandalone.showAds`. It is important - however - that the original placeholders are destroyed in the HTML, as having multiple instances of the same placeholder ID on a page will cause unpredictable ad behaviour. When using `ezstandalone.destroyPlaceholders`, make sure you don't call it too early. This could cause the ads on the page the user is currently viewing to disappear! ## Removing all placeholders You can remove all placeholders on the page by using the `destroyAll` function. ```html ``` As with `destroyPlaceholders` - these locations can later be recalled with the `showAds` function. ## Show all placeholders You can call ads in every placeholder on a given page by using the `showAds` function, without defining any value. ```html ``` --- ## Troubleshooting Source: https://docs.ezoic.com/docs/ezoicads/troubleshooting/ When setting up EzoicAds on your site, it's important to ensure that everything is functioning properly. We provide a built-in JavaScript Integration Debugger that allows you to quickly diagnose issues with your ad setup. Below is a step-by-step guide on how to use this debugger and interpret its outputs. ## Step 1: Trigger the Debugger To activate the debugger, simply append the following query parameter to the URL of the page where your EzoicAds are integrated: ``` ez_js_debugger=1 ``` For example: ``` https://www.yourwebsite.com?ez_js_debugger=1 ``` Once the query parameter is added and the page loads, a green modal dialog will appear at the bottom center of the screen. This is the JavaScript Integration Debugger. ## Step 2: Understanding the Debugger Output The debugger modal contains several key pieces of information that will help you troubleshoot your setup. Here’s a breakdown of the information provided: - **Script In Page `` Element**: The debugger verifies the presence of the Ezoic integration script (`sa.min.js`) in the page's `` element. This ensures the script is optimally positioned for effective page loading. - **Consent**: This section checks for the use of Ezoic consent management tools, including an API call or the presence of the Consent Management Platform (CMP) script on the page. These checks ensure that user privacy is managed in compliance with regulations. For more information on privacy management, see the [Privacy Documentation](/docs/ezoicads/privacy/). - The CMP script checks include verifying its presence on the page, its placement within the page's `` element, and ensuring it appears before Ezoic's integration script (`sa.min.js`) in the HTML structure. - **Ad Request**: The debugger tracks whether an ad request to Ezoic's servers is successfully sent and provides key details, such as the word count and the maximum number of allowed ads. - This section includes a word count consistency check to ensure ad requests are not sent too early—before the primary page content has fully loaded. Maintaining a consistent word count helps verify that dynamic content remains stable, ensuring accurate ad rendering. - **Defined Placeholders**: This section provides detailed information about the ad placeholder ids used in the last network request to Ezoic. - For each ID, the debugger displays the corresponding HTML element on the page, whether the ID was selected for ad insertion, and its associated ad unit name and size. - **Unused Placeholders**: This section lists the IDs of ad placeholders that are present in the page's HTML but were not included in the most recent network request to Ezoic. - **API Methods Called**: The debugger displays each method invoked on the `ezstandalone` API, displaying them in the order of execution along with their provided arguments. This detailed tracking helps identify potential implementation issues. ## Step 3: Using the Debugger for Troubleshooting The information provided in the debugger modal is invaluable for diagnosing common issues such as: - **Ads Not Displaying**: Check the placeholder detection and ad status to ensure placeholders are defined and ads are assigned. - **Ad Requests Failing**: If ad requests aren't being sent or are failing, the debugger will provide error messages that point to potential misconfigurations. - **Script Loading Issues**: If the script isn’t properly loaded, verify that the script tag is present in your source code and correctly configured. ## Conclusion The EzoicAds JavaScript Integration Debugger is a simple but powerful tool to help you ensure that your ad setup is functioning as intended. By following these steps, you can quickly identify and resolve common issues, ensuring that your ads display properly and without disruption. # Privacy --- ## GDPR Compliance Source: https://docs.ezoic.com/docs/privacy/gdpr/ ## Compliance ### Privacy Policy You must provide Ezoic with the link to your privacy policy. This can be done at [https://pubdash.ezoic.com/settings/privacy/privacypolicy](https://pubdash.ezoic.com/settings/privacy/privacypolicy). Your privacy policy must also include additional wording specific to Ezoic, the instructions for doing so and the wordings can be found at the same link. ### GDPR and Consent Management To handle GDPR compliance, there are two options: 1. Using the free Ezoic TCF 2.2 consent management platform (Recommended) 2. Connect to an existing TCF 2.2 consent management platform To learn more about GDPR and how Ezoic comes into play, feel free to checkout this [support article](https://support.ezoic.com/kb/article/ezoic-and-gdpr)! ## Using the Ezoic CMP (Recommended) 1. Add the following scripts to the head of your website **before** any ad / tracking code, as covered in [the Ad Set-up steps](/docs/ezoicads/implementation/). ```html ``` __Warning:__ This code **must not be delayed**, otherwise personal information might be processed before consent is given. ### Customizing the ezoic CMP The Ezoic CMP can be customized by visiting the [privacy section](https://pubdash.ezoic.com/settings/privacy/consentmanagement) within the ezoic dashboard. # Advanced --- ## Anchor Ads Source: https://docs.ezoic.com/docs/ezoicadsadvanced/anchor-ads/ By default, Ezoic will show anchor ads if enabled in the dashboard under the [Ezoic Ads](https://pubdash.ezoic.com/ezoicads) tab. ## Turning Off Anchor Ads To turn the Anchor Ad off for a specific page, the `ezstandalone.setEzoicAnchorAd` function can be used. In order for this functionality to work, it must be called prior to `ezstandalone.showAds()`. ```html ``` ## Checking If Anchor Ad Was Closed To see if the Anchor Ad has been closed for a user's session, use the `hasAnchorAdBeenClosed` function. Below is an example of using the function to determine whether to keep showing the Anchor Ad ```html ``` --- ## Ezoic Video Source: https://docs.ezoic.com/docs/ezoicadsadvanced/ezoic-video/ The Embed Code Generator from your Ezoic Video dashboard can be used to add our Video Player to your website. --- ## Advanced Source: https://docs.ezoic.com/docs/ezoicadsadvanced/advanced/ ## Overview EzoicAds provides advanced features that allow publishers to fine-tune the behavior of the ad library. These features can be used to customize the behavior of the ad library to better suit the needs of your site. ### Configurable Options There are configurable options available in EzoicAds that can be used to customize the behavior of the ad library. These options can be set using the `ezstandalone.config()` function. #### Setting Configuration Options To set configuration options, use the following syntax: ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ // Configuration options go here }); }); ``` **Important:** These configuration options must be set after initialization of the EzoicAds [header scripts](https://docs.ezoic.com/docs/ezoicads/integration/#header-script) and before calling `ezstandalone.showAds()`. ### Available Options | Option | Type | Default | Description | | ---------------------------------------------- | ------- | ------------ | ---------------------------------------------------------------------------- | | [`limitCookies`](#limit-cookies) | Boolean | `false` | Enables more precise control over cookie usage on your site. | | [`anchorAdPosition`](#anchor-ad-position) | String | `bottom` | Change the position of the anchor ad to be at the top or bottom of the page. | | [`anchorAdExpansion`](#anchor-ad-expansion) | Boolean | `true` | Allow collapsible anchor ads to expand in height on mobile devices. | | [`disableInterstitial`](#disable-interstitial) | Boolean | `false` | Completely disable all interstitial ads on your site. | | [`vignetteDesktop`](#vignette-ads) | Boolean | _(optional)_ | Enable or disable vignette (interstitial) ads on desktop devices. | | [`vignetteMobile`](#vignette-ads) | Boolean | _(optional)_ | Enable or disable vignette (interstitial) ads on mobile devices. | | [`vignetteTablet`](#vignette-ads) | Boolean | _(optional)_ | Enable or disable vignette (interstitial) ads on tablet devices. | --- #### Limit Cookies When enabled, the Limit Cookies feature ensures that only essential cookies required by Ezoic are included by default. This provides greater control over user privacy and helps with compliance to various data protection regulations. To enable Limit Cookies: ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ limitCookies: true }); }); ``` --- #### Anchor Ad Position Allows you to change the position of the Anchor Ad to be at the top or bottom of the page. Acceptable values are 'top' or 'bottom'. The Anchor Ad will be located at the bottom of the page by default. For example to set the anchor ad position to be at the top of the page: ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ anchorAdPosition: "top" }); }); ``` --- #### Anchor Ad Expansion Allows you to set the expansion behavior for collapsible anchor ads on mobile devices. Collapsible anchor ads are allowed to expand by default. To disable anchor ad expansion: ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ anchorAdExpansion: false }); }); ``` --- #### Disable Interstitial Allows you to completely disable all interstitial ads on your site. When enabled, no interstitial ads (including vignette ads) will be displayed. To disable all interstitial ads: ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ disableInterstitial: true }); }); ``` This setting takes precedence over individual vignette device settings. If `disableInterstitial` is set to `true`, no interstitial ads will display regardless of `vignetteDesktop`, `vignetteMobile`, or `vignetteTablet` settings. --- #### Vignette Ads Vignette ads (also known as interstitial ads) are full-screen ads that display between page content or during natural transition points. You can control their display behavior on different device types. By default, vignette ads follow your site's global settings. Use these options to override the behavior for specific device types: **Enable vignette ads on desktop only:** ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ vignetteDesktop: true, vignetteMobile: false, vignetteTablet: false }); }); ``` **Disable vignette ads on mobile devices:** ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ vignetteMobile: false }); }); ``` **Enable vignette ads on all devices:** ```javascript ezstandalone.cmd.push(function() { ezstandalone.config({ vignetteDesktop: true, vignetteMobile: true, vignetteTablet: true }); }); ``` If you don't specify a vignette option, the system will use your site's global vignette settings configured in your Ezoic dashboard. --- _More options will be added in the future. Please check back for updates._ --- ### Tracking Data If you would like to track data even on pages that are not showing ads you can include the script below. This is specifically helpful in the starting stages of testing when you are not ready to show ads yet. ```html ``` --- ### Splitting Traffic Unlike our other integration methods, splitting traffic happens clientside. Using the `ezstandalone.isEzoicUser` function, you can split traffic on a percentage of your traffic. Like the traffic splitting in our cloud integrations the `isEzoicUser` function splits based on a user's session, not pageviews. ### Example Below is an example of splitting 50 percent of your traffic with Ezoic. ```html ``` --- ## ShowAds Advanced Usage The advanced implementation provides additional functionality by accepting an array of objects. Each object can include the following attributes: - **id** (required): The unique identifier of the placeholder where the ad should be shown. - **required** (optional, boolean): A flag indicating whether the ad must be displayed. If set to `true`, the system will force an ad to be shown in the specified placeholder, even if it would not normally be displayed. - **sizes** (optional, string or array of strings): Specifies the allowed sizes for the ad in the format `'{width}x{height}'`. You can provide a single size as a string or multiple sizes as an array of strings. This allows you to control the dimensions of the ad that will be displayed. ### Example ```html ``` In this example: 1. **Placeholder 103**: - An ad will always be displayed in placeholder `103`. - The allowed sizes for the ad are `336x280` and `126x126`. 2. **Placeholder 104**: - An ad will be displayed in placeholder `104` if Ezoic decides this ad should be shown. - The allowed size for the ad is `1000x450`. 3. **Placeholder 105**: - An ad will always be displayed in placeholder `105`. - No specific sizes are provided, so Ezoic will decide the best size for this placeholder. ### Notes - **Specificity of Ad Sizes**: The ad sizes specified in the `sizes` attribute are treated as specific requests. Ezoic will attempt to find the best possible ad that fits the given size. If an exact match is not available, the system will choose the closest available size that can best fit within the specified dimensions. - If the `required` attribute is set to `true`, Ezoic will prioritize showing the ad in that placeholder, ensuring it is displayed even if other conditions might normally prevent it. - If `sizes` are specified, the ad will only be displayed if an ad of the specified sizes is available. If the `sizes` attribute is omitted or left empty, Ezoic will use its default behavior to determine the ad size. ### Use Cases - **Guaranteed Ad Placement**: Use the `required` attribute to ensure that ads are shown in critical placeholders, regardless of other conditions. - **Size-Specific Ads**: Use the `sizes` attribute to control the dimensions of the ads being displayed. This is particularly useful for responsive designs or specific layout requirements where certain sizes are more effective. --- ## RefreshAds `refreshAds` allows for placeholders to be refreshed without needing to call `destroyPlaceholders` and `showAds`. This is useful for sites with dynamic content or infinite scroll where the content changes but the placeholders remain the same. Multiple placeholders can be passed in as an array of IDs. ### Example ```html ``` --- ## Rewarded Ads Source: https://docs.ezoic.com/docs/ezoicadsadvanced/rewarded/ Rewarded ads are a type of ad that allows users to view an ad for a minimum amount of time in exchange for a reward. Rewarded ads fill the entire display, similar to how interstitial ads are displayed. Two key differences are that video ads can be displayed in addition to banner ads, and there is a timer that must be completed before the reward is granted. The time remaining is displayed to the user as it counts down. The user can close the ad at any time, but if it is closed before the timer is up, the reward will not be granted. The user will be prompted to confirm that they want to close the ad early and forfeit the reward. The ad remains on screen after the timer has expired, at which point the user can close the ad without forfeiting the reward. ## Integration We provide an interface for requesting and displaying the ads (detailed below), and we notify your code when the ad window is closed, and whether the reward was granted, through a callback. You are responsible for integrating the rewards into your app. This includes asking the user if they want to view the ad, and handling the reward when it is granted. Rewarded ads can be requested to be shown at any time. After requesting, there will be a short delay (1-2 seconds) while we fetch an ad before it is ready to be shown. You must always ask the user if they want to view the ad before showing it, and you cannot mislead or incentivize the user to view the ad. **Note on Callback Functions:** The examples below use arrow functions for callbacks. Arrow functions preserve the lexical `this` context from the enclosing scope. If you need to use `this` within your callback and are using anonymous function expressions instead of arrow functions, make sure to use `.bind(this)` to preserve the correct context: ```javascript // Arrow function (recommended) - preserves `this` context window.ezRewardedAds.requestAndShow((result) => { this.handleResult(result); // `this` refers to enclosing scope }); // Anonymous function with .bind(this) if `this` is needed window.ezRewardedAds.requestAndShow(function(result) { this.handleResult(result); // `this` is preserved via .bind() }.bind(this)); ``` ## Reward Restrictions You are free to choose the reward that you offer to the user. However, there are some restrictions on what you can offer: 1. The reward may not be a direct monetary item under any circumstance. Examples include cash, cryptocurrency, or gift cards. 2. The reward may be an indirect monetary item, as long as it is non-transferrable, and only redeemable within your platform, website, or app. - Indirect monetary items are items with monetary value that aren't a direct form of payment in the real world. If the reward is a discount or voucher for a physical item, they must not exceed 25% of the item's value. - Examples of indirect monetary items include discounts, loyalty rewards or points, product free shipping, product or service free trials, game character extra lives, and game character skins. 3. Random rewards are allowed with some restrictions: - You must disclose the odds of receiving each reward before the user agrees to view the ad. - Details on all rewards must be easily accessible to the user. - The odds of receiving any reward must be greater than zero. 4. More than one rewarded ad can be required to be watched back-to-back for one reward, but this must be clearly disclosed to the user before they accept to watch the ads. You can read more about Google's rewarded ad policies here: https://support.google.com/admanager/answer/7496282 ## Initialization The following code must be included before any other rewarded ad functions are called, no matter what integration type you are using. Ideally, this code should be included in the `` of your page, or at least at the top of the ``. ```javascript window.ezRewardedAds = window.ezRewardedAds || {}; window.ezRewardedAds.cmd = window.ezRewardedAds.cmd || []; ``` ### Javascript Integration If you are integrated with Javascript, the page must have the `ezstandalone` initialization, as well as at least one call to initialize the ads. If the page does not already initialize ads (e.g., with `showAds()` or similar), you can use `initRewardedAds()` to load the rewarded ads code along with any other ad types you want enabled. Note that this will not request a rewarded ad, that must be done separately. If you already have ads on the page, you only need the `ezRewardedAds` initialization code. ```html ``` If the page does not already have ads, the following code is the minimal integration required to load the rewarded ads code: ```html ``` ### Cloud Integration If you are cloud integrated, then most of the code needed to initialize rewarded ads will be loaded automatically when the page loads. The only code you need to manually add to the `` of your site is simply: ```html ``` ### Controlling Site-Wide Ad Types When using `initRewardedAds()`, you can control which other ad types are enabled site-wide by passing a configuration object. This is useful if you want to disable certain ad types on pages that use rewarded ads, and serves as an alternative to setting up page rules in your Ezoic dashboard. **Note:** You can still use page rules in your dashboard to control ad types if you prefer that approach. The function parameters provide a code-based alternative for developers who want to control ad placement programmatically. #### Parameters The `initRewardedAds()` function accepts an optional configuration object with the following properties: - **anchor** (Boolean, optional): Whether to enable anchor ads. Default is `true`. - **interstitial** (Boolean, optional): Whether to enable interstitial ads. Default is `true`. - **video** (Boolean, optional): Whether to enable video ads (floating outstream). Default is `true`. - **sideRails** (Boolean, optional): Whether to enable side rail ads. Default is `true`. #### Usage Examples ##### Default (All Ad Types Enabled) ```javascript ezstandalone.initRewardedAds(); // Equivalent to: // ezstandalone.initRewardedAds({anchor: true, interstitial: true, video: true, sideRails: true}); ``` ##### Only Rewarded Ads (Disable All Other Types) ```javascript ezstandalone.initRewardedAds({ anchor: false, interstitial: false, video: false, sideRails: false }); ``` ##### Custom Configuration ```javascript ezstandalone.initRewardedAds({ anchor: true, // Keep anchor ads interstitial: false, // Disable interstitial ads video: true, // Keep video ads sideRails: false // Disable side rail ads }); ``` ## Checking if the code is loaded The rewarded ads code will not be ready immediately after the page loads, although the delay is quite short, around 1-2 seconds on most connections. You should also consider that the code may not ever be loaded in some situations, such as if the network request fails, or if the user is using a browser that is blocking ad code. There are two ways to ensure that the code is loaded before calling any of the functions: 1. **Checking the `ezRewardedAds.ready` property**: You can check if the `ezRewardedAds` object is ready by checking the `ready` property. This property will be `true` once the code is loaded. This is useful when you have a specific moment in time that you want to display a rewarded ad, such as at the end of a level in a game, or when the user clicks a button. This also ensures that you are only interrupting user interaction when the rewarded ad code is ready to be used. If you are using this method, you don't need to use the `cmd` queue. ```javascript if (window.ezRewardedAds.ready) { // Your code here } else { // The code is not ready yet } ``` 2. **Using the `cmd` queue**: The `cmd` queue is a list of functions that will be called as soon as the rewarded ads code is ready. This method is useful if you would like to show a rewarded ad as soon as possible after the page loads. You can also use the `cmd` queue to call your own functions once the code is loaded, such as displaying a button to request a rewarded ad. Keep in mind that if the rewarded ad code fails to load, the functions in the `cmd` queue will not be called. ```javascript window.ezRewardedAds.cmd.push(() => { // Your code here }); ``` ## Quick Start ### Javascript Integration The following example shows how to load the rewarded ads code and display a button that will request a rewarded ad when clicked. The button will only be displayed once the code is loaded. ```html ``` ### Cloud Integration This is the same example as above, but without the `ezstandalone` code. The rewarded ads code will be loaded automatically when the page loads. ```html ``` ## Usage ### requestAndShow() This method requests a rewarded ad and shows it immediately if the ad is ready. It takes a callback function as a parameter, which is called when the ad is closed and indicates whether the reward was granted. You must still ensure that you are notifying the user that they will be watching an ad to take an action (For example, text next to the button saying "watch an ad for a free life"). #### Usage Examples ##### Basic Example This example shows the most basic usage. All default values are used, and we don't need to check the reward outcome, since alwaysCallback is set to `false` by default. All we need to set is the callback function, which is the action that will be taken if and only if the reward is granted ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestAndShow(grantReward); }); function grantReward() { console.log("Reward granted!"); } ``` ##### Full Example This example uses all available options, and serves mostly as a reference to copy-paste from. ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestAndShow( (result) => { // Callback function if (result.status) { if (result.reward) { console.log("Reward granted!"); } else { console.log("User closed the ad early, no reward granted."); } } else { console.log("Rewarded ad request failed:", result.msg); } }, { // Config object rewardName: "Main Page Credits Reward", alwaysCallback: true, rewardOnNoFill: false } ); }); ``` #### Parameters - **callback** (Function): A function executed when the ad window is closed. The function receives a single result object with the following properties: - **status** (Boolean): - `true` if the ad was closed and no error occurred. - `false` if an error occurred (e.g., if the ad was not ready or if there was an internal error). - **reward** (Boolean): Whether the reward was granted. - **msg** (String): A message detailing the outcome (e.g., `"ad closed"` or an error message). - **adInfo** (Object): Information about the ad (only present when `status` is `true`). Contains: - **id** (String): Unique identifier for the ad. - **estimatedPayout** (Number): Estimated payout value for the ad. - **config** (Object, optional): An object containing configuration options. The object can contain the following properties: - **rewardName** (String, optional): The name of the rewarded ad to identify usage or location for analytics. Accepts alphanumeric characters, spaces, and some punctuation. Default is `""`. - **alwaysCallback** (Boolean, optional): Whether to call the callback function even if the reward is not granted. Default is `false`. - **rewardOnNoFill** (Boolean, optional): Whether to grant the reward in the event that an ad does not fill, or there is an internal error. Useful when combined with `alwaysCallback = false` and you don't want to prevent a user action if an ad cannot be shown. The reward will not be granted if the user closes the ad early. Default is `false`. - **minCPM** (Number, optional): The minimum CPM (cost per thousand impressions) for the ad to be shown. If no ad meets this CPM, the ad will not be shown and the callback will be called with `status = false`. Default is `0`, which means there is no minimum CPM. ### requestWithOverlay() This method requests a rewarded ad and displays a call-to-action asking the user if they want to view the ad. It provides several options for customizing the overlay, including the title, message, and button text. It also provides options for adjusting the overlay and reward behavior. #### Parameters - **callback** (Function): A function executed when the ad request completes. The function receives a single result object with the following properties: - **status** (Boolean): - `true` if the ad loaded and the user had a chance to be able to view the ad. - `false` if an error occurred or if the ad went unfilled. - **reward** (Boolean): Whether the reward was granted. - **msg** (String): A message detailing the outcome (e.g., `"ad ready"` or an error message). - **adInfo** (Object): Information about the ad (only present when `status` is `true`). Contains: - **id** (String): Unique identifier for the ad. - **estimatedPayout** (Number): Estimated payout value for the ad. - **text** (Object): An object containing the text to display in the call-to-action. The object can contain the following properties: - **header** (String, optional): The title of the call-to-action. Default is `"Watch Ad to Continue?"`. - **body** (String Array, optional): The message to display in the call-to-action. Each array entry is one line. Default is no body text. - **accept** (String, optional): The text for the button. Default is `"Watch ad"`. - **cancel** (String, optional): The text for the cancel button. Default is `"Cancel"`. - **config** (Object, optional): An object containing configuration options for the call-to-action. The object can contain the following properties: - **rewardName** (String, optional): The name of the rewarded ad to identify usage or location for analytics. Accepts alphanumeric characters, spaces, and some punctuation. Default is `""`. - **alwaysCallback** (Boolean, optional): Whether to call the callback function even if the reward is not granted. Default is `false`. - **lockScroll** (Boolean, optional): Whether to lock the scroll position when the call-to-action is displayed. This is useful if you are gating content behind a reward. Default is `false`. - **rewardOnNoFill** (Boolean, optional): Whether to grant the reward in the event that an ad does not fill, or there is an internal error. Useful when combined with `alwaysCallback = false` and you don't want to prevent a user action if an ad cannot be shown. The reward will not be granted if the user declines to watch the ad, or if they close the ad early. Default is `false`. - **dontAsk** (Boolean, optional): If `true`, the call-to-action will not be shown, and the ad will be requested and shown immediately. You must still ensure that you are notifying the user that they will be watching an ad to take an action (For example, text next to the button saying "watch an ad for a free life"). Default is `false`. - **minCPM** (Number, optional): The minimum CPM (cost per thousand impressions) for the ad to be shown. If no ad meets this CPM, the ad will not be shown and the callback will be called with `status = false`. Default is `0`, which means there is no minimum CPM. #### Usage Examples ##### Basic Example This example shows the most basic usage. All default values are used, and we don't need to check the reward outcome, since alwaysCallback is set to `false` by default. All we need to set is - The callback function, which is the action that will be taken if and only if the reward is granted - The body text, which we need to set to inform the user of what the reward is for. ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestWithOverlay(grantReward, {body: ['You will get a reward for watching this ad.']}); }); function grantReward() { console.log("Reward granted!"); } ``` ##### Replacing a button event This example sets `rewardOnNoFill` to `true`, which means that callback will still be called even if an ad cannot be found, or if there is another error. This is useful if you want to replace a button event with a rewarded ad, but you don't want to prevent the user from taking the action if an ad cannot be found. This also checks if the rewarded ads code has loaded, and if it hasn't, it will call the `takePremiumAction()` function directly. ```html ``` ##### Using alwaysCallback This example sets `alwaysCallback` to `true`, which means that the callback will be called even if the reward is not granted. This allows you to handle the case where the user declines to watch the ad, or if an ad cannot be found. This is useful if you want to take an action regardless of whether the ad was shown or not. This example also demonstrates how to use an arrow function as the callback to allow for the result parameter to be passed to another function, in this case `handleRewardResult`. ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestWithOverlay( (result) => { return handleRewardResult(result); }, {body: ["You will receive 10 credits for watching this ad."]}, {alwaysCallback: true} ); }); function handleRewardResult(result) { if (result.status) { if (result.reward) { takePremiumAction(); } else { displayMessageToUser("Sorry, you did not receive a reward."); } } else { displayMessageToUser("Sorry, there was an error loading the ad."); // It is up to you whether to still take the premium action in this case, since the user did not have a chance to view the ad. } } function takePremiumAction() { console.log("Premium action taken!"); } function displayMessageToUser(message) { console.log(message); } ``` ##### Using rewardName for Analytics This example demonstrates how to use the `rewardName` parameter to track different rewarded ad placements for analytics purposes. ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestWithOverlay( grantExtraLife, {body: ['Watch an ad to get an extra life!']}, {rewardName: 'Grant Extra Life'} ); }); window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestWithOverlay( unlockPremiumFeature, {body: ['Watch an ad to unlock this premium feature.']}, {rewardName: 'Premium Feature Unlock'} ); }); function grantExtraLife() { console.log("Extra life granted!"); } function unlockPremiumFeature() { console.log("Premium feature unlocked!"); } ``` ##### Full Example This example uses all available options, and serves mostly as a reference to copy-paste from. ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.requestWithOverlay( (result) => { // Callback function if (result.status) { if (result.reward) { console.log("Reward granted!"); } else { console.log("User either declined to watch the ad, or they closed the ad early."); } } else { console.log("Rewarded ad request failed:", result.msg); } }, { // Text object header: "Watch Ad to Continue?", body: ["You will receive 10 credits for watching this ad.", "Click the button below to watch the ad."], accept: "Watch ad", cancel: "Cancel" }, { // Config object rewardName: "Main Page Credits Reward", alwaysCallback: true, lockScroll: true, rewardOnNoFill: false } ); }); ``` ## Advanced Usage These functions allow for direct access to the two stages of rewarded ads: requesting and showing the ad. You can use these functions to create your own custom overlay or UI for asking the user if they want to view the ad, or if you want to integrate the ad more directly into your site, for example a button in a game. Keep in mind that you are still required to ask the user in some way whether they want to view the ad. ### request() This method requests a rewarded ad. It takes a callback function as a parameter, which is called once the ad is ready, if the ad went unfilled, or if an error occurs. - `request()` **can** be called: - even if `show()` was never called (e.g., if the user declined to view the ad). After calling `request()` again, `show()` can then be called as normal. - before the Ezoic rewarded ads code loads. It will be queued and executed once the code is loaded (this is the purpose of `window.ezRewardedAds.cmd.push()` in the example). There should only be a very brief delay between the page loading (or, in the case of a standalone integration, the first call to `ezstandalone.showAds()` or `initRewardedAds()`) and the rewarded ad code loading. - once `request()` has been called, it **cannot** be called: - until the callback is called. Only one request can be made at a time. - while an ad is already showing (ie. after `show()` is called but before the ad window is closed). #### Parameters - **callback** (Function): A function executed when the ad request completes. The function receives a single result object with the following properties: - **status** (Boolean): - `true` if the ad is ready. - `false` if an error occurred or if the ad went unfilled. - **msg** (String): A message detailing the outcome (e.g., `"ad ready"` or an error message). - **adInfo** (Object): Information about the ad (only present when `status` is `true`). Contains: - **id** (String): Unique identifier for the ad. - **estimatedPayout** (Number): Estimated payout value for the ad. - **config** (Object, optional): An object containing configuration options. The object can contain the following properties: - **minCPM** (Number, optional): The minimum CPM (cost per thousand impressions) for the ad to be shown. If no ad meets this CPM, the ad will not be shown and the callback will be called with `status = false`. Default is `0`, which means there is no minimum CPM. #### Usage Example ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.request((result) => { if (result.status) { console.log("Rewarded ad is ready"); // Ask the user if they want to view the ad } else { console.log("Rewarded ad request failed:", result.msg); } }); }); ``` ### show() This method displays the rewarded ad that was loaded using `request()`. It takes one parameter: a callback function that is called when the ad is closed and indicates whether the reward was granted. #### Parameters - **callback** (Function): A function executed when the ad window is closed. The function receives a single result object with the following properties: - **status** (Boolean): - `true` if the ad was closed and no error occurred. - `false` if an error occurred (e.g., if the ad was not ready or if there was an internal error). - **reward** (Boolean): Whether the reward was granted. - **msg** (String): A message detailing the outcome (e.g., `"ad closed"` or an error message). - **adInfo** (Object): Information about the ad (only present when `status` is `true`). Contains: - **id** (String): Unique identifier for the ad. - **estimatedPayout** (Number): Estimated payout value for the ad. - **config** (Object, optional): An object containing configuration options. The object can contain the following properties: - **rewardName** (String, optional): The name of the rewarded ad to identify usage or location for analytics. Accepts alphanumeric characters, spaces, and some punctuation. Default is `""`. **Usage Example:** ```javascript window.ezRewardedAds.show((closeResult) => { if (closeResult.status) { console.log("Rewarded ad closed"); if (closeResult.reward) { console.log("Reward granted!"); } } else { console.log("Failed to show rewarded ad:" + closeResult.msg); } }); ``` **Usage Example with rewardName:** ```javascript window.ezRewardedAds.show((closeResult) => { if (closeResult.status) { console.log("Rewarded ad closed"); if (closeResult.reward) { console.log("Extra credits reward granted!"); addCreditsToAccount(10); } } else { console.log("Failed to show rewarded ad:" + closeResult.msg); } }, { rewardName: "Extra Credits Reward" }); function addCreditsToAccount(amount) { console.log(`Added ${amount} credits to account`); } ``` ### Complete Advanced Usage Example Below is a full example demonstrating how to request and show a rewarded ad, including prompting the user to confirm ad viewing The example uses the built-in `confirm()` function to ask the user if they want to view the ad. This is just an example, and you can use any method you like to ask the user if they want to view the ad. The example uses console logging to indicate the status of the ad and whether the reward was granted. You can replace this with your own code to handle the various outcomes. ```javascript // Ensure the global object is initialized window.ezRewardedAds = window.ezRewardedAds || {}; window.ezRewardedAds.cmd = window.ezRewardedAds.cmd || []; window.ezRewardedAds.cmd.push(() => { // Queue a command to request and show a rewarded ad window.ezRewardedAds.request((requestResult) => { // Request a rewarded ad if (requestResult.status) { if (confirm("Watch ad for reward?")) { // Ask the user if they want to watch the ad for a reward window.ezRewardedAds.show((closeResult) => { if (closeResult.status) { console.log("Rewarded ad closed"); if (closeResult.reward) { console.log("Reward granted!"); } } else { console.log("Failed to show rewarded ad:" + closeResult.msg); } }); } else { // User declined to watch the ad } } else { console.log("Rewarded ad request failed:", requestResult.msg); } }); }); ``` Note that the call to `show()` does not need to be inside the `request()` callback. You can call `show()` at any time after the callback provided to `request()` has been called and `result.status` is true: ```javascript // Ensure the global object is initialized window.ezRewardedAds = window.ezRewardedAds || {}; window.ezRewardedAds.cmd = window.ezRewardedAds.cmd || []; // Request a rewarded ad window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.request((requestResult) => { if (requestResult.status) { // Ask the user if they want to view the ad. For example, display a button that calls showRewardedAd() when clicked } else { console.log("Rewarded ad request failed:", requestResult.msg); } }); }); function showRewardedAd() { window.ezRewardedAds.show((closeResult) => { if (closeResult.status) { console.log("Rewarded ad closed"); if (closeResult.reward) { console.log("Reward granted!"); } } else { console.log("Failed to show rewarded ad:" + closeResult.msg); } }); } ``` ## Error Handling & Considerations - **Single Request at a Time:** If an ad is already loading, subsequent calls to `request()` or `requestWithOverlay()` will trigger an error callback (`result.status = false`). Wait for the current ad load to complete before calling `request()` again. - **Ad Readiness:** Calling `show()` when no ad is ready will result in an error callback (`result.status = false`) with a message like `"rewarded ad not ready. call request() first"`. - **Valid Callbacks:** Always pass a valid function to the callback argument to all methods. If an argument is not provided, or if the provided argument is not a function, a warning is logged and no further action will be taken. ## Specialized Rewarded Ad Types ### Content Locker Content Locker is a specialized implementation of rewarded ads that gates specific content or actions behind ad viewing. It automatically selects the highest revenue ad format from multiple types (rewarded video, interstitial, or outstream video ads) to maximize revenue while providing a seamless user experience. #### Key Features - **Multi-format competition**: Automatically competes rewarded video ads against interstitial and outstream video ads, selecting the format with the highest CPM - **Smart fallbacks**: If the primary rewarded ad doesn't fill, it intelligently falls back to alternative ad formats - **Flexible actions**: Supports both URL redirects and callback functions as the gated action - **Loading states**: Optional loading overlay to improve user experience during ad loading - **Customizable UI**: Configurable call-to-action text and styling #### Usage The Content Locker is accessed via the `contentLocker()` method: ```javascript window.ezRewardedAds.contentLocker(action, config) ``` #### Parameters - **action** (String or Function): The action to gate behind the ad - If a string, it will be treated as a URL to redirect to after the ad - If a function, it will be called after the ad is completed - **config** (Object, optional): Configuration options for the content locker #### Configuration Options - **loadingOverlay** (Boolean, optional): Whether to show a loading overlay while the ad loads. Default is `true`. - **readyCallback** (Function, optional): Called when the ad is ready to show (before display). Default is `null`. - **rewardName** (String, optional): The name of the rewarded ad to identify usage or location for analytics. Accepts alphanumeric characters, spaces, and some punctuation. Default is `""`. - **minCPM** (Number, optional): The minimum CPM (cost per thousand impressions) for the ad to be shown. If no ad meets this CPM, the ad will not be shown and the callback will be called with `status = false`. Default is `0`, which means there is no minimum CPM. - **callToAction** (Object, optional): Customizes the call-to-action overlay text: - **disabled** (Boolean): If `true`, skips the overlay and shows the ad immediately. Default is `false`. - **header** (String): Header text for the overlay. Default is `"Before Continuing"`. - **body** (String): Body text for the overlay. Default is `"Please watch a short ad from our sponsors"`. - **button** (String): Button text for the overlay. Default is `"Watch Ad and Continue →"`. #### Basic Examples ##### URL Redirect Gate a URL redirect behind an ad: ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.contentLocker("https://example.com/premium-content"); }); ``` ##### Function Callback Gate a function call behind an ad: ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.contentLocker(() => { console.log("Premium action executed!"); unlockPremiumFeature(); }); }); function unlockPremiumFeature() { // Your premium feature code here } ``` #### Advanced Examples ##### Custom Call-to-Action Text ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.contentLocker( "https://example.com/premium-content", { callToAction: { header: "Unlock Premium Content", body: "Watch a quick ad to access exclusive content", button: "Unlock Content" } } ); }); ``` ##### With Loading Overlay and Ready Callback ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.contentLocker( () => { downloadFile(); }, { loadingOverlay: true, readyCallback: (result) => { console.log("Ad ready status:", result.status); }, callToAction: { header: "Download Premium File", body: "Support our site by watching a short ad", button: "Start Download" } } ); }); ``` ##### Skip Overlay (Direct Ad Display) For cases where you want to show the ad immediately without asking: ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.contentLocker( "https://example.com/download", { callToAction: { disabled: true // Skip the overlay, show ad immediately } } ); }); ``` ##### Using rewardName for Analytics Tracking Track different content locker placements for analytics by using the `rewardName` parameter: ```javascript window.ezRewardedAds.cmd.push(() => { window.ezRewardedAds.contentLocker( "https://example.com/premium-article", { rewardName: "Premium Article Access" } ); }); ``` #### Integration with HTML Elements Content Locker can be easily integrated with buttons or links: ```html ``` ## Pulling Rewarded ID Stats via BDA API You can retrieve detailed statistics for your rewarded ads using the BDA (Big Data Analytics) API. This allows you to track performance metrics, revenue data, and other analytics for your rewarded ad implementations. ### API Endpoint The BDA API endpoint for custom data retrieval is: ``` POST https://api-gateway.ezoic.com/gateway/bdaservices/getCustomData/?developerKey=YOUR_DEVELOPER_KEY ``` **Note:** You can find your `developerKey` and additional documentation about generating API requests in your publisher dashboard under **Settings > API**. ### Sample Request Here's an example of how to request information for a specific rewarded id: **Note:** Replace `YOUR_DOMAIN_ID` with your actual domain ID (use the getDomains endpoint from the API documentation in pubdash to find this), and `YOUR_REWARD_ID` with the specific reward ID you want to query. ```text curl -X POST "https://api-gateway.ezoic.com/gateway/bdaservices/getCustomData/?developerKey=YOUR_DEVELOPER_KEY" \ -H "Content-Type: application/json" \ --data '{ "StartDate": "2025-08-12", "EndDate": "2025-08-13", "Platform": "ALL", "DomainId": YOUR_DOMAIN_ID, "DimensionColumns": [ { "Data": "reward_id", "Type": "string" }, { "Data": "reward_status", "Type": "string" }, { "Data": "is_matched", "Type": "number" } ], "MetricColumns":[ { "Data": "reward_revenue", "Type": "number" } ], "Order":{ "ColumnNumber":0, "Direction":"DESC" }, "Filters": [ { "Type": "INCLUDE", "FilterKey": "reward_id", "OperationId": "EXACTLY", "FilterValue": "YOUR_REWARD_ID" } ] }' ``` ### Sample Response The API returns data in the following format: ```json { "Message": "", "Success": true, "Data": [ { "is_matched": "1", "reward_id": "YOUR_REWARD_ID", "reward_revenue": "$0.00", "reward_status": "not completed" } ] } ``` ### Understanding the Response Data Each data object in the response above contains the following fields: #### is_matched - **Type**: String (representing a number) - **Values**: "1" (processed) or "0" (not processed) - **Description**: Indicates whether the rewarded ad data has been fully processed in Ezoic's system. A value of "1" means the data has been processed and the revenue and status information is finalized. A value of "0" means the data is not yet processed, and the revenue or status values are not final yet. #### reward_id - **Type**: String - **Description**: A unique identifier for each specific rewarded ad request. This ID is generated when a rewarded ad is requested and can be obtained from the `adInfo.id` property in the callback functions documented above. Use this ID to filter for specific rewarded ad instances in your analytics. #### reward_revenue - **Type**: String (formatted as currency) - **Description**: The revenue generated from this specific rewarded ad ID. #### reward_status - **Type**: String - **Possible Values**: - "completed" - User watched the full ad and received the reward - "not completed" - User closed the ad early or didn't meet the completion requirements - **Description**: Indicates the completion status of the rewarded ad. --- ## Next.js Source: https://docs.ezoic.com/docs/ezoicadsadvanced/nextjs/ Ezoic’s standalone script is designed for traditional multi-page sites. Since Next.js uses client-side navigation, we must manually trigger Ezoic to scan the DOM and cleanup placeholders. ## Global Types Create `types/ezoic.d.ts` to ensure type safety across your components. ```typescript declare global { interface Window { ezstandalone?: { cmd: Array<() => void>; showAds: (...ids: number[]) => void; destroyPlaceholders: (...ids: number[]) => void; }; } } export {}; ``` ## Global Script Initialization Add the scripts to `app/layout.tsx`. Initializing the `cmd` queue here ensures that any subsequent calls to Ezoic are buffered until the library is fully loaded. ```typescript import Script from "next/script"; import EzoicRouteHandler from "@/components/EzoicRouteHandler"; export default function RootLayout({ children }: { children: React.ReactNode }) { return (