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

# Bright SDK for iOS/tvOS - Integration Guide

> This guide is for developers who want to monetize iOS/tvOS applications with Bright SDK.

export const UpdateSDK = ({platform}) => <>
    <AccordionGroup>
      <Accordion title="Option A - Using the Integration CLI Tool (Recommended)">
        <p>Run the tool with the <code>--update</code> flag. It will automatically fetch and replace <code>brdsdk.xcframework</code> in place without losing your config or consent flow settings:</p>

        <p><strong>iOS:</strong></p>
        <pre><code className="language-bash">{`npx github:BrightSDK/bright-sdk-integration --platform ios --update`}</code></pre>

        <p><strong>tvOS:</strong></p>
        <pre><code className="language-bash">{`npx github:BrightSDK/bright-sdk-integration --platform tvos --update`}</code></pre>
      </Accordion>

      <Accordion title="Option B - Manual">
        <h3>Updating in an Xcode Project</h3>
        <ol>
          <li>Download the latest SDK from the Bright SDK Dashboard and unzip it.</li>
          <li>Replace <code>brdsdk.xcframework</code> in its current location (e.g., <code>&lt;MyProject&gt;/Libraries</code>).</li>
          <li>Clean the build folder: Product → Clean Build Folder in Xcode.</li>
        </ol>
        
        <img src="/snippets/image/update_SDK_iOS_1.png" alt="Alt text" width="400" />
        <p>If cleaning doesn't help, clear <code>DerivedData</code>...</p>

        {platform === "ios" && <>
            <h3>Updating in a Unity Project</h3>
            <ol>
              <li>Remove the existing <code>brdsdk.unitypackage</code> asset from Unity Editor.</li>
            </ol>
            <img src="/snippets/image/update_SDK_iOS_2.png" alt="Alt text" width="400" />
            <p>Re-import the new package following <a href="https://docs.bright-sdk.com/integration-guides/ios-tvos#option-b-manual:~:text=Import%20the%20SDK%20Package">Import the SDK Package</a> Step.</p>
          </>}
      </Accordion>
    </AccordionGroup>
  </>;

export const SubmitIntegrationReview = ({platform}) => <>
    <p><strong>Pre-Submission Requirements</strong></p>
    <p>The Bright Data SDK compliance team will verify:</p>
    <ul>
      <li>SDK integration UX and functionality.</li>
      <li>Consent screen implementation.</li>
      <li>Opt-out mechanism.</li>
      <li>User value proposition.</li>
    </ul>

    <ol>
      <li>
        <strong>Submission Process</strong>
        <Note>
          Self-check using an emulator/simulator is not yet supported. Currently, self-check can only be performed on a real device.
        </Note>
        <ol type="a">
          <li>
            <strong>Run Self-Check (takes a few minutes)</strong> — Complete the self-check verification to identify potential issues before submission:
            <ul>
              <li>Navigate to the <a href="https://bright-sdk.com/cp/apps">Bright SDK Dashboard</a> and click your appID.</li>
              <li>Scroll down to "Implementation self-check", click "Get started".</li>
              <li>Install the app on the test device and follow the instructions.</li>
              <li>If the self-check passed successfully, submit it for review!</li>
            </ul>
            <Note>
              <strong>If the SDK isn't initializing / peer not connecting:</strong>
              <ol>
                <li>Verify the correct App ID is used, confirm the SDK service is running.</li>
                <li>Check there aren't multiple SDK apps running from the same IP — that can interfere.</li>
                <li>If nothing helps, check with our team.</li>
              </ol>
            </Note>
          </li>
          <li>
            <strong>Submit for review via Dashboard</strong>
            <ul>
              <li>Navigate to the <a href="https://bright-sdk.com/cp/apps">Bright SDK Dashboard</a>.</li>
              <li>Select your app ID.</li>
              <li>Click "Submit for Review".</li>
              <li>Complete the compliance checklist to validate adherence to guidelines.</li>
              <li>Upload your package.</li>
            </ul>
          </li>
        </ol>
      </li>
      <li>
        <strong>Store submission</strong> — You will be notified by email once your app is approved for release. The app status in the dashboard will also be changed to "Approved".
        {platform !== "ios" && platform !== "macos" && platform !== "android" && <>
            <p>Guides to help you through the store review:</p>
            <ul>
              <li><a href="https://docs.bright-sdk.com/integration-guides/how-to-upload-apps-to-the-lg-store">LG</a></li>
              <li><a href="https://docs.bright-sdk.com/integration-guides/how-to-upload-apps-to-the-samsung-store">Samsung</a></li>
            </ul>
          </>}
      </li>
      <li>
        <strong>Review Resources</strong>
        <ul>
          <li>Watch our <a href="https://www.youtube.com/watch?v=kQCmca0FHyw">guided tour video</a> for critical submission tips.</li>
          <li>Review our <a href="https://bright-sdk.com/blog/monetization-optimization/ensuring-excellence-bright-sdks-guidelines-for-excellent-apps">quality standards</a> for faster approval.</li>
        </ul>
      </li>
    </ol>

    {platform === "ios" && <>
        <p><strong>For iOS/tvOS — How to submit your build:</strong></p>

        <ul>
          <li>Paste a public link in the "Submit for Review" window on the dashboard, OR</li>
          <li>Send via TestFlight to all 4 addresses below (one invite per address):</li>
        </ul>

        <table>
          <thead>
            <tr>
              <th>Email</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>sdk@brightdata.com</td>
            </tr>
            <tr>
              <td>sdk+1@brightdata.com</td>
            </tr>
            <tr>
              <td>sdk+2@brightdata.com</td>
            </tr>
            <tr>
              <td>sdkcompliance@brightdata.com</td>
            </tr>
          </tbody>
        </table>
      </>}

    <Info>
      We will review each app up to 3 times. 3 rejections or failure to meet minimum quality standards may result in final rejection.
    </Info>
  </>;

export const Tos = ({platform}) => <>
    <p><strong>App Store Privacy Settings</strong></p>

    <p>Bright SDK does not collect any personal information except the user's IP address. Bright Data knows that a certain IP <em>exists</em> but not who owns it or any other information.</p>

    {platform === "ios" && <>
        <p>Your existing privacy settings may already cover this (e.g., if you have ads in your app). If not, update your App Store privacy settings to include at minimum what Bright Data collects:</p>

        <img src="/snippets/image/apple_update_tos_1.png" alt="Alt text" width="400" />
      </>}

    <p><strong>Update Your FAQ and Terms of Service</strong></p>

    <p>Add the following text to your Terms of Service web page (TOS, EULA, or Privacy Policy):</p>

    <p><em>In return for premium features of '[Your App Name]', you may choose to be a peer on the Bright Data network. By doing so, you agree to have read and accepted the <a href="https://bright-sdk.com/eula">Bright SDK EULA</a> and <a href="https://bright-sdk.com/privacy-policy">Bright Data's Privacy Policy</a>.</em></p>

    <p><em>You may opt out of the Bright Data network by [add clear opt-out instructions].</em></p>

    <p><strong>Requirements</strong></p>

    <ul>
      <li>Include all text and links as provided above.</li>
      <li>Any additional Bright SDK-related content must be shared during the app review process for approval.</li>
    </ul>
  </>;

export const CustomConsentApple = ({platform}) => <>
    <p>While the standard Bright SDK consent screen is always available, we highly encourage customization to match your app's look & feel, this typically leads to higher conversion rates. There are two customization options:</p>

    <table>
      <thead>
        <tr>
          <th>Option</th>
          <th>Description</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Consent Dialog Customization</td>
          <td>Modify the built-in Bright SDK consent screen</td>
        </tr>
        <tr>
          <td>Custom Consent Screen</td>
          <td>Build your own consent UI entirely</td>
        </tr>
      </tbody>
    </table>

    <AccordionGroup>
      {}
      <Accordion title="Option 1 - Custom Consent Screen">
        <Warning>
          <strong>Subject to Bright SDK approval.</strong> Please contact Bright SDK before implementing to get pre-approved.
        </Warning>

        {platform === "ios" && <>
            <p>This is what it looks like on the default Bright SDK screen:</p>
            <img src="/snippets/image/iOS_Custom_Consent_Screen_1.png" alt="Default iOS Screen" width="400" />
          </>}

        {platform === "macos" && <>
            <p>This is what it looks like on the default Bright SDK screen:</p>
            <img src="/snippets/image/iOS_Custom_Consent_Screen_2.png" alt="Default MacOS Screen" width="400" />
          </>}

        <p><strong>Design Requirements</strong></p>
        <p>Your custom consent screen must include the following mandatory elements:</p>

        <p><strong>Mandatory text:</strong></p>

        <pre><code className="language-text">{`"To [Benefit to user], please allow Web Indexing by Bright Data to use your device's free resources and IP address to download public web data from the Internet while you are using the app.
None of your personal information is collected, except your IP address. Bright Data does not track you."`}</code></pre>

        <pre><code className="language-text">{`"Read Bright Data's Privacy Policy and End User License Agreement"`}</code></pre>

        <p><strong>Required links:</strong></p>

        <table>
          <thead>
            <tr>
              <th>Text</th>
              <th>URL</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Bright Data</td>
              <td><a href="https://brightdata.com/">https://brightdata.com/</a></td>
            </tr>
            <tr>
              <td>Privacy Policy</td>
              <td><a href="https://bright-sdk.com/privacy-policy">https://bright-sdk.com/privacy-policy</a></td>
            </tr>
            <tr>
              <td>End User License Agreement</td>
              <td><a href="https://bright-sdk.com/eula">https://bright-sdk.com/eula</a></td>
            </tr>
          </tbody>
        </table>

        <p><strong>Interactive element:</strong></p>
        <p>Tapping "public web data" must open a popup with additional information:</p>

        <img src="/snippets/image/iOS_Custom_Consent_Screen_3.png" alt="Popup Info" width="400" />

        <p><strong>Translations:</strong></p>
        <p>If you wish to translate your screen, use only the <a href="https://docs.google.com/spreadsheets/d/1G0Y1CY9emvfM9qlGC4o7wM-ypWqHbGo5Jxx8rT7DCVs/edit?gid=0#gid=0">provided official translations</a>. Contact your partnership manager for any missing languages.</p>

        <p><strong>For tvOS:</strong></p>
        <p>Replace links with: <em>"Scan the QR Code to learn more about Bright Data policy and ethical usage".</em></p>
        <p>
          Use your own branded QR code or a <a href="https://media.bright-sdk.com/2023/09/qr-bright-sdk-faq.svg">hosted</a> version pointing to:<br />
          <a href="https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing">https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing</a>
        </p>

        <p><strong>Examples of possible custom consent screens:</strong></p>

        <Columns cols={2}>
          <Column>
            <img src="/snippets/image/iOS_Custom_Consent_Screen_4.png" alt="Custom Consent Example 1" width="300" />
          </Column>
          <Column>
            <img src="/snippets/image/iOS_Custom_Consent_Screen_5.png" alt="Custom Consent Example 2" width="300" />
          </Column>
        </Columns>

        <p><strong>Integration Code</strong></p>
        <ul>
          <li>Pass <code>skip_consent: true</code> in the SDK initializer to prevent the default consent screen from showing.</li>
          <li>The opt-in button (e.g., "I Agree") should call <code>external_opt_in()</code>.</li>
          <li>The opt-out button (e.g., "I Disagree") should call <code>opt_out()</code>.</li>
          <li>After presenting your custom screen, call <code>consent_shown()</code>.</li>
        </ul>

        <p><strong>Flow of Showing the Consent Screen</strong></p>
        <ol>
          <li>Call <code>brd_api.authorizeDevice()</code> - status must be <code>.authorized</code> to proceed</li>
          <li>Present your custom consent screen</li>
          <li>Call <code>brd_api.consent_shown()</code> after the screen is presented to register its display</li>
          <li>Call <code>external_opt_in()</code> on agree, <code>opt_out()</code> on disagree</li>
        </ol>
      </Accordion>

      {}
      <Accordion title="Option 2 - Consent Dialog Customization">
        <p>All customization parameters are available for Xcode-level integration. A subset is available for Unity Editor-level integration via <code>BrdsdkBridge.cs</code>.</p>
        <p>You can customize the consent dialog by passing additional parameters during SDK initialization. The following subsections cover all available customization options.</p>

        <AccordionGroup>
          <Accordion title="Background Images">
            <p>You can set background images for portrait and landscape orientations. Supported scale modes:</p>
            <ul>
              <li><code>ScaleToFill</code> - stretches to fill, may change aspect ratio</li>
              <li><code>ScaleAspectFit</code> - fits within bounds, transparent areas remain</li>
              <li><code>ScaleAspectFill</code> - fills bounds, some content may be clipped</li>
            </ul>
            <p>Landscape image is optional - portrait will be used as fallback.</p>

            <p><strong>Unity:</strong></p>
            <pre><code className="language-csharp">{`ConsentBackgroundImage backgroundImage = new ConsentBackgroundImage();
// By xcasset name (add the image to xcassets in Xcode after export):
backgroundImage.portraitImage = "portrait";
// Or by file path:
backgroundImage.landscapeImage = Path.Combine(Application.dataPath, "Raw/landscape.jpg");
backgroundImage.scaleMode = ConsentBackgroundImage.ScaleMode.ScaleAspectFill;

BrdsdkBridge.init("To support this app", "I Agree", "I disagree",
    "opt-out instructions", appicon, choiceChanged, skip_consent,
    language, colors, backgroundImage, optIn, optOut);`}</code></pre>

            <p><strong>Swift:</strong></p>
            <pre><code className="language-swift">{`let background = ConsentBackgroundImage(portraitName: "portrait", landscapeName: "landscape")

try brd_api(background_image: background, skip_consent: true, campaign: nil) { choice in
    let choice = Choice(rawValue: choice) ?? .none
    self.choice = choice
}`}</code></pre>

            <p><strong>Objective-C:</strong></p>
            <pre><code className="language-objectivec">{`ConsentBackgroundImage *background = [[ConsentBackgroundImage alloc]
    initWithPortraitName:@"portrait"
           landscapeName:@"landscape"
               scaleMode:UIViewContentModeScaleAspectFill
                      in:NSBundle.mainBundle];

(void)[[brd_api alloc] initWithBenefit:NULL agree_btn:NULL disagree_btn:NULL
    opt_out_instructions:@"<OPT-OUT INSTRUCTIONS>"
    appicon:[UIImage imageNamed:@"<YOUR APP ICON NAME>"]
    cwd:NULL sys_app_id:NULL language:NULL colors:NULL
    background_image:background opt_in_info:NULL opt_out_info:NULL
    fonts:NULL skip_consent:YES campaign:NULL error:&error
    on_choice_change:^(NSInteger choice) {
        ViewController *vc = (ViewController *)[application getKeyWindow].rootViewController;
        vc.choice = choice;
    }];`}</code></pre>
          </Accordion>

          <Accordion title="Action Button Images (Opt-In / Opt-Out)">
            <p>Customize the opt-in and opt-out button appearance. For each button you can set:</p>
            <ul>
              <li>A background image (overrides background color if set)</li>
              <li>A text image (overrides button text if set)</li>
              <li>A background color</li>
              <li>A text color</li>
            </ul>

            <p><strong>Unity:</strong></p>
            <pre><code className="language-csharp">{`ConsentActionInfo optIn = new ConsentActionInfo(
    null, null,
    unchecked((Int32)0xffdb8e5a),
    unchecked((Int32)0xff36271d)
);
ConsentActionInfo optOut = new ConsentActionInfo(
    Path.Combine(Application.streamingAssetsPath, "opt_out_bg.png"),
    Path.Combine(Application.streamingAssetsPath, "opt_out_text.png"),
    null, null
);

BrdsdkBridge.init("To support this app", "I Agree", "I disagree",
    "opt-out instructions", appicon, choiceChanged, skip_consent,
    language, colors, backgroundImage, optIn, optOut);`}</code></pre>

            <p><strong>Swift:</strong></p>
            <pre><code className="language-swift">{`let optIn = ConsentActionInfo(backgroundName: "opt_in_bg", textName: "opt_in_text")
let optOut = ConsentActionInfo(backgroundName: "opt_out_bg", textName: "opt_out_text")

try brd_api(opt_in_info: optIn, opt_out_info: optOut, skip_consent: true, campaign: nil) { choice in
    let choice = Choice(rawValue: choice) ?? .none
    self.choice = choice
}`}</code></pre>

            <p><strong>Objective-C:</strong></p>
            <pre><code className="language-objectivec">{`ConsentActionInfo *optIn = [[ConsentActionInfo alloc]
    initWithBackgroundName:@"opt_in_bg" textName:@"opt_in_text" in:NSBundle.mainBundle];
ConsentActionInfo *optOut = [[ConsentActionInfo alloc]
    initWithBackgroundName:@"opt_out_bg" textName:@"opt_out_text" in:NSBundle.mainBundle];`}</code></pre>
          </Accordion>

          <Accordion title="Consent Icon">
            <ul>
              <li><strong>Native SDK:</strong> Pass a <code>UIImage</code> via the <code>appicon</code> parameter in the <code>brd_api</code> initializer.</li>
              <li><strong>Unity:</strong> Pass an image path or its <code>xcassets</code> name via the <code>appicon</code> parameter in <code>BrdsdkBridge.init()</code>.</li>
            </ul>
          </Accordion>

          <Accordion title="Colors">
            <p>Use <code>ColorSettings</code> (Swift/ObjC) or <code>ConsentColors</code> (Unity) to customize consent screen element colors.</p>

            <p><strong>Unity:</strong></p>
            <pre><code className="language-csharp">{`ConsentColors colors = new ConsentColors();
colors.backgroundColor       = unchecked((Int32)0xffEFF0E9);
colors.titleColor            = unchecked((Int32)0xff741313);
colors.consentMessageColor   = unchecked((Int32)0xff50C7C7);
colors.consentLinksColor     = unchecked((Int32)0xff506BC7);
colors.privacyColor          = unchecked((Int32)0xff658582);
colors.privacyLinksColor     = unchecked((Int32)0xff656785);
colors.iconsForegroundColor  = unchecked((Int32)0xff344d70);
colors.iconsBackgroundColor  = unchecked((Int32)0xffe7effa);

BrdsdkBridge.init("To support this app", "I Agree", "I disagree",
    "opt-out instructions", appicon, choiceChanged, skip_consent,
    language, colors, backgroundImage, optIn, optOut);`}</code></pre>

            <p><strong>Swift/Objective-C:</strong> Use the <code>ColorSettings</code> class — see API Documentation for full property list.</p>
          </Accordion>

          <Accordion title="Fonts">
            <p>Use <code>ConsentFontsInfo</code> to override default fonts. You can set fonts for:</p>
            <ul>
              <li>Title text</li>
              <li>Main text</li>
              <li>Under-icons text</li>
              <li>License text</li>
              <li>Buttons text</li>
            </ul>

            <Warning>
              <strong>Warning:</strong> The SDK has limitations for font sizes.
            </Warning>

            <p><strong>Unity:</strong></p>
            <pre><code className="language-csharp">{`ConsentFontsInfo fonts = new ConsentFontsInfo();
string fontPath = Path.Combine(Application.streamingAssetsPath, "CroissantOne-Regular.ttf");
string registeredFontName = "BebasNeue-Regular"; // must be listed in Info.plist

fonts.titleText   = new ConsentFontsInfo.ConsentFont(fontPath, 20);
fonts.mainText    = new ConsentFontsInfo.ConsentFont(fontPath, 16);
fonts.licenseText = new ConsentFontsInfo.ConsentFont(registeredFontName, 14);
fonts.buttonsText = new ConsentFontsInfo.ConsentFont(fontPath, 16);

BrdsdkBridge.init("To support this app", "I Agree", "I disagree",
    "opt-out instructions", appicon, choiceChanged, skip_consent,
    language, colors, backgroundImage, optIn, optOut, fonts);`}</code></pre>

            <p><strong>Swift/Objective-C:</strong> Use the <code>ConsentFontsInfo</code> class — see API Documentation for full constructor and method list.</p>
          </Accordion>
        </AccordionGroup>
      </Accordion>
    </AccordionGroup>
  </>;

export const OptInOut = ({platform}) => <>
    <Danger>
      The user must always be able to opt out of Bright SDK after giving their initial consent.
    </Danger>

    <p>Your app must include a settings option allowing users to opt in or out at any time. This is typically placed in a Settings menu.</p>

    <p><strong><u>Requirements:</u></strong></p>
    <ul>
      <li>Add a toggle/switch labeled "Web Indexing" that clearly reflects the current status (opted in or out).</li>
      <li>Below the switch, add text emphasizing the value users receive when opting in. (<a href="h#add-opt-in/out-settings-option:~:text=Value%20text%20suggestions%3A">see examples</a>)</li>
      
      <li>Include a "Learn more" link that opens: <a href="https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing">https://bright-sdk.com/users#learn-more-about-bright-sdk-web-indexing</a>.</li>
    </ul>
    <Note>
  Every time the user toggles Web Indexing <strong>ON</strong>, the consent screen must reappear — regardless of any previous opt-in.
</Note>

    {platform === "ios" && <>
        <p><strong><u>Implementation:</u></strong></p>
        <ul>
          <li>Use <code>get_choice()</code> to get the current status for the switch/checkbox.</li>
          <li>When the user disables the switch → call <code>opt_out()</code>.</li>
          <li>When the user enables the switch → call <code>show_consent()</code> (the user must actively opt in through the consent screen).</li>
          <li>Use the <code>on_choice_change</code> callback to keep the UI automatically updated.</li>
        </ul>
      </>}

    {platform === "macos" && <>
        <p><strong><u>Implementation:</u></strong></p>
        <ul><li>Set the initial checkbox state based on the current SDK choice:</li></ul>
        <pre><code>{`bright_sdk_checkbox.state = (sdk?.choice == .peer) ? .on : .off`}</code></pre>
        <ul><li>Add control logic for the checkbox:</li></ul>
        <pre><code>{`@IBOutlet weak var bright_sdk_checkbox: NSButton!

@IBAction func bright_sdk_checkbox_action(_ sender: NSButton) {
    if bright_sdk_checkbox.state == NSControl.StateValue.off {
        bright_sdk_checkbox.state = .off
        sdk?.opt_out()
    } else {
        bright_sdk_checkbox.state = .on
        show_bright_sdk()
    }
}`}</code></pre>
      </>}

    <Note>
      There is no way to directly opt in. Only the user can decide. You must show the consent screen — opt-in happens automatically only if the user agrees.
    </Note>

    <p><strong><u>Value text suggestions:</u></strong></p>
    <table>
      <thead>
        <tr><th>State</th><th>Example text</th></tr>
      </thead>
      <tbody>
        <tr><td><code>Opted out</code></td><td>"Enable to see fewer ads"</td></tr>
        <tr><td><code>Opted out</code></td><td>"Enable to get 100 extra coins"</td></tr>
        <tr><td><code>Opted out</code></td><td>"Enable to enjoy premium features"</td></tr>
        <tr><td><code>Opted in</code></td><td>"When enabled you see fewer ads"</td></tr>
        <tr><td><code>Opted in</code></td><td>"When enabled you get 100 extra coins"</td></tr>
      </tbody>
    </table>

    <p>Refrain from using technical terms like "opt in" / "opt out" — always speak in terms of user value.</p>

    <p>You may add a confirmation dialog to discourage opting out (e.g., <em>"If you disable Web Indexing, you will start seeing ads. Continue?"</em>), and a confirmation message after opting out (e.g., <em>"Web Indexing disabled. You can re-enable it anytime from Settings."</em>)</p>

    <p><strong><u>Common mistakes to avoid:</u></strong></p>
    <table>
      <thead>
        <tr>
          <th>Issue</th>
          <th>Guidance</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Label reads "Bright" or "Bright SDK"</td>
          <td>Label must read "Web Indexing"</td>
        </tr>
        <tr>
          <td>No value text</td>
          <td>Always include text describing what the user gains</td>
        </tr>
        <tr>
          <td>No "Learn more" link</td>
          <td>Required — must link to the URL above</td>
        </tr>
        <tr>
          <td>Switch doesn't reflect current state</td>
          <td>Switch must always show the true current status</td>
        </tr>
      </tbody>
    </table>
  </>;

### Requirements

* iOS 13.0 or newer / tvOS 15.0 or newer.
* Xcode (13.4 or newer recommended).
* Bright SDK for iOS/tvOS ([latest](https://bright-sdk.com/cp/docs/sdk/ios)).
* For Unity projects: Unity Editor 2020.2.5f1 or newer.

<Note>
  Bright Data **must** review your application **before** you submit it to the Apple App Store. Send your test build via TestFlight for review.
</Note>

### Important Notes

* Take care when implementing the consent screen and the opt-out mechanisms in a way which follows guidelines in this document.
* Users must **always, voluntarily** decide to opt in after seeing the consent screen, and must **always** have an easy way to opt out.
* Bright Data recommends offering value in exchange for opting in (e.g., fewer ads, bonus coins, premium features). However, simply asking for user support is also acceptable.
* Do not suggest Bright SDK as an alternative to paying for premium items or subscriptions via the App Store. **This violates App Store policy**.
* **Bright SDK does not do any user tracking**. It is not related to Apple's ATT (App Tracking Transparency). You may show the consent screen regardless of ATT status.
* Bright Data reviews SDK integration after initial release and regularly thereafter. Your account will be terminated if you violate the guidelines in this document.
* Starting from version 1.385.451, Bright SDK checks for parental controls. If enabled, the consent screen will **NOT** be displayed - this is by design to ensure informed consent.

<Steps>
  <Step title="Create App ID on Dashboard" titleSize="h3">
    If you haven't done this yet, log in to [your dashboard](https://bright-sdk.com/cp/apps) and create your app ID first.

    The App ID for iOS/tvOS apps is constructed as follows: `ios_<your Apple Bundle ID>`

    **Example:** If your Bundle ID is `com.mycompany.MyGame`, your App ID will be `ios_com.mycompany.MyGame`.
  </Step>

  <Step title="Install SDK Files" titleSize="h3">
    You can set up the Bright SDK framework in your iOS/tvOS app in two ways:

    * [**Using the Bright SDK Integration CLI Tool**](https://brightsdk.github.io/bright-sdk-integration/) <Badge color="green">Recommended</Badge> - automatically downloads the SDK, extracts the framework, and patches your Xcode project with the necessary references.
    * **Manually** - download the SDK from the dashboard, unzip it, and copy the files yourself.

    Either way, you will still need to add the SDK initialization code to your app.

    <AccordionGroup>
      <Accordion title={<span>Option A - Using the Integration CLI Tool <Badge color="green" size="md">Recommended</Badge></span>}>
        Run the tool using the [`bright-sdk-integration`](https://brightsdk.github.io/bright-sdk-integration/) CLI. See the [Apple example](https://github.com/BrightSDK/bright-sdk-integration-example-apple) for full setup instructions.

        The tool will:

        * Download the latest BrightSDK zip from `cdn.bright-sdk.com/static/`
        * Extract `brdsdk.xcframework` into `BrightSDK/`
        * Patch your `project.pbxproj` - adding `brdsdk.xcframework` with Embed & Sign and setting `FRAMEWORK_SEARCH_PATHS`
        * Save `brd_sdk.config.json` for future runs

        Once the tool completes, skip to [Step 3 - Integrate Bright SDK](#integrate-bright-sdk).
      </Accordion>

      <Accordion title="Option B - Manual">
        Download the latest Bright SDK using the [Bright SDK downloader](https://brightsdk.github.io/bright-sdk-downloader-rs/). Unzip it.

        **SDK Structure and overview**

        | Component                          | Description                                                                                                                                   |
        | :--------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
        | `brdsdk.xcframework`               | Universal framework for Xcode. Contains iPhoneOS & Simulator builds. Min iOS: 13.0, Min tvOS: 15.0                                            |
        | `unity_plugin/brdsdk.unitypackage` | Unity plugin package for Unity-level integration                                                                                              |
        | `unity_sample_app_2020.2.5`        | Reference sample for Unity integration at the Unity Editor level                                                                              |
        | `unity_xcode_sample_app`           | Reference sample for Unity integration at the Xcode level. Note: Missing `UnityFramework.framework` — build and copy it from your own project |
        | `sample_tvos_xcode`                | Reference sample for tvOS Xcode integration                                                                                                   |
        | `xcode_swiftui_sample_app`         | Reference sample for native iOS using SwiftUI                                                                                                 |
        | `xcode_uikit_sample_app`           | Reference sample for native iOS using UIKit (Swift or Objective-C)                                                                            |
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Integrate Bright SDK" titleSize="h3">
    Choose the integration path that matches your project type:

    | Project Type               | Integration Path                                                                                                                                                                                                                                                              |
    | :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Native iOS (Swift)         | [Step 3.1](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.1%20Embedding%20the%20Framework%20in%20Xcode) → [Step 3.2](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.2%20Integration%20in%20Xcode%20\(iOS%20%E2%80%93%20Swift\))         |
    | Native iOS (Objective-C)   | [Step 3.1](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.1%20Embedding%20the%20Framework%20in%20Xcode) → [Step 3.3](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.3%20Integration%20in%20Xcode%20\(iOS%20%E2%80%93%20Objective%2DC\)) |
    | tvOS                       | [Step 3.1](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.1%20Embedding%20the%20Framework%20in%20Xcode) → [Step 3.4](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.4%20Integration%20in%20Xcode%20\(tvOS\))                            |
    | Unity (Unity Editor level) | [Step 3.5](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.5%20Integration%20in%20Unity%20Editor)                                                                                                                                                           |
    | Unity (Xcode level)        | [Step 3.1](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.1%20Embedding%20the%20Framework%20in%20Xcode) → [Step 3.6](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.6%20Integration%20in%20Xcode%20\(Unity\))                           |

    <Steps>
      <Step title="3.1 Embedding the Framework in Xcode">
        This step is common to all Xcode-based integrations (native iOS, tvOS, and Unity at Xcode level).

        <Note>
          **CLI Tool users:** The framework is already extracted and referenced in your `.xcodeproj` - confirm Embed & Sign is set and skip to 3.2.
        </Note>

        1. Copy `brdsdk.xcframework` into your app's project folder (e.g., `<MyProject>/Libraries`)

        2. Open your project in Xcode

        3. In the **Project Navigator** (left pane), select the project at the top

        4. Select your app target under the **Targets** list

                   <img src="https://mintcdn.com/brightdata-31a14106/pkPzFIQJLdPO3rSx/integration-guides/image/tvOS_Integrate_Bright_SDK_1.png?fit=max&auto=format&n=pkPzFIQJLdPO3rSx&q=85&s=c58c13b10a393689fafc3c4aa37d83fb" alt="Xcode Project Navigator" width="600" data-path="integration-guides/image/tvOS_Integrate_Bright_SDK_1.png" />

        5. Go to the **General** tab → scroll to **Frameworks, Libraries, and Embedded Content**

        6. Click **+** → **Add Other…** → **Add Files**

        7. Locate and select `brdsdk.xcframework` → click **Open**

        8. Confirm that it shows **Embed & Sign** next to `brdsdk.xcframework`

                   <img src="https://mintcdn.com/brightdata-31a14106/pkPzFIQJLdPO3rSx/integration-guides/image/tvOS_Integrate_Bright_SDK_2.png?fit=max&auto=format&n=pkPzFIQJLdPO3rSx&q=85&s=911db5039dd37903e77c84b0a3227754" alt="Embed and Sign" width="600" data-path="integration-guides/image/tvOS_Integrate_Bright_SDK_2.png" />
      </Step>

      <Step title="3.2 Integration in Xcode (iOS – Swift)">
        Reference sample: `xcode_swiftui_sample_app`, `xcode_uikit_sample_app`

        **Short steps:**

        1. Import the framework: `import brdsdk`
        2. Initialize the SDK via the `brd_api` constructor (see example below). Typically done in the app delegate on the app-launched event.
        3. Show the consent screen:
           * Pass `skip_consent: false` → consent screen appears automatically on initialization
           * Pass `skip_consent: true` → you must call `brd_api.show_consent()` manually later
        4. To disable the SDK, call `brd_api.opt_out()`

        <Warning>
          It is not recommended to initialize the SDK on the main thread.
        </Warning>

        Here's the example:

        **Initialization:**

        ```swift theme={null}
        do {
            try brd_api(
                benefit: "<BENEFIT>",
                agree_btn: "<AGREE>",
                disagree_btn: "<DISAGREE>",
                language: "en",
                skip_consent: true,
                campaign: nil
            ) { [weak self] choice in
                // handle updated choice
            }
            uuidTextField.text = brd_api.get_uuid()
        } catch {
            let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .cancel))
            present(alert, animated: true)
        }
        ```

        **Presenting the consent screen manually:**

        ```swift theme={null}
        brd_api.show_consent(self)
        ```

        **Opting out:**

        ```swift theme={null}
        brd_api.opt_out()
        ```
      </Step>

      <Step title="3.3 Integration in Xcode (iOS – Objective-C)">
        Reference sample: `xcode_uikit_sample_app`

        **Short steps:**

        1. Import the framework: `#import <brdsdk/brdsdk.h>`
        2. Initialize the SDK by calling `brd_api` constructor. Typically done in the app delegate on the app-launched event.
        3. Show the consent screen:
           * Pass `NO` to `skip_consent` → consent screen appears automatically on initialization
           * Pass `YES` to `skip_consent` → you must call `[brd_api show_consent]` manually later
        4. To disable the SDK, call `[brd_api opt_out]`

        <Warning>
          It is not recommended to initialize the SDK on the main thread.
        </Warning>

        Here's the example:

        **Initialization:**

        ```objective-c theme={null}
        NSError *error = nil;
        __weak typeof(self) wSelf = self;

        (void)[[brd_api alloc] initWithBenefit:NULL
                                     agree_btn:NULL
                                  disagree_btn:NULL
                          opt_out_instructions:NULL
                                       appicon:[UIImage imageNamed:@"appicon"]
                                           cwd:NULL
                                   sys_app_id:NULL
                                      language:NULL
                                        colors:NULL
                              background_image:background
                                   opt_in_info:NULL
                                  opt_out_info:NULL
                                         fonts:NULL
                                  skip_consent:YES
                                      campaign:NULL
                                         error:&error
                              on_choice_change:^(NSInteger choice) {
            // handle updated choice
        }];
        ```

        **Presenting the consent screen manually:**

        ```objective-c theme={null}
        [brd_api show_consent:self benefit:@"<BENEFIT>" agree_btn:@"<AGREE>" disagree_btn:@"<DISAGREE>" language:@"en"];
        ```

        **Opting out:**

        ```objective-c theme={null}
        [brd_api opt_out];
        ```
      </Step>

      <Step title="3.4 Integration in Xcode (tvOS)">
        Reference sample: `sample_tvos_xcode`

        <Info>
          **Note:** Please contact our partnership managers to share information about your tvOS app before beginning implementation.
        </Info>

        Bright SDK must show a consent screen right after the app is launched. Your app must initialize the main screen first, show the consent screen, and only then pass control to other functions/screens.

        1. Embed the framework - follow [Step 3.1](https://docs.bright-sdk.com/integration-guides/ios-tvos#option-b-manual:~:text=3.1%20Embedding%20the%20Framework%20in%20Xcode).
        2. Open `SampleAppApp.swift` from `sample_tvos_xcode` and implement similar SDK initialization logic in your app.
        3. Open `SettingsView.swift` from `sample_tvos_xcode` and implement the settings screen similarly:
           * **Web Indexing** section should have **Enable** and **Disable** buttons.
           * Button actions delegate to `enableIndexingCallback`, then to `ContentViewModel.setIndexing(enable:, callback:)` (defined in `ContentView.swift`), which calls:
             * `brd_api.show_consent()` - to enable the SDK.
             * `brd_api.opt_out()` - to disable the SDK.
      </Step>

      <Step title="3.5 Integration in Unity Editor">
        This section will guide you on how to integrate SDK **at Unity level** (no code changes in Xcode).

        Reference sample: `unity_sample_app_2020.2.5`, `unity_admob_sample_app`

        *Use this path if you want to integrate Bright SDK entirely at the Unity level without modifying Xcode. If you prefer to integrate at the Xcode level instead, skip to [Step 3.6](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.6%20Integration%20in%20Xcode%20\(Unity\)). Do not follow both - choose one.*

        <Tip>
          If you have other 3rd-party frameworks that need to initialize before your game launches, integrating via the Unity plugin ensures the correct user flow: Bright SDK consent screen → 3rd party initialization → game launch.
        </Tip>

        We recommend Unity Editor 2020.2.5f1. If you encounter issues, use `unity_sample_app_2020.2.5` as a reference.

        **<u>3.5.1 Import the SDK Package</u>**

        1. In Unity Editor, go to **Assets → Import Package → Custom Package**
        2. Select `brdsdk.unitypackage` from the `unity_plugin` folder
        3. In the **Import Unity Package** dialog, click **Import**
           * This adds `brdsdk.framework`, `BrdsdkBridge.cs`, and other required files
        4. Confirm there are no compilation errors

        **<u>3.5.2 Add SDK Initialization to Your Code</u>**

        1. Open `BrightDataSDK/BrdsdkBridge.cs` and review the available SDK API calls
        2. Call `BrdsdkBridge.init(...)` from the `Start()` method of your game object handler (e.g., instead of direct ad initialization)
        3. Implement the `on_choice_callback` method properly - see `BrightDataSDK/Sample/SampleBehaviour.cs` for an example. The result of consent will be delivered via this callback.
        4. Implement the Settings screen following Step 4: Add Opt-In/Out Settings Option, using `BrightDataSDK/Sample/SettingsBehaviour.cs` as a reference

        **<u>3.5.3 Generate the Xcode Project</u>**

        1. Go to **File → Build Settings** and switch to the iOS platform
        2. Click **Player Settings**:
           * Scroll to **Other Settings**
           * Set **Target SDK** to Device SDK
           * Set **Target minimum iOS Version** to `12` or higher
           * Update **Bundle Identifier** and other settings as needed
        3. Close Player Settings
        4. In **Build Settings**, click **Build** and choose the destination folder
        5. Wait for the Xcode project to be generated

        **<u>3.5.4 Run the App on a Device</u>**

        1. Select the main project scheme (usually selected by default)
        2. Connect your iPhone and select it as the target device
        3. Configure **Signing & Capabilities** for the main project target
        4. Confirm New Build System is selected: **File → Project Settings → Build System**
        5. Press **Product → Run** (⌘R)
      </Step>

      <Step title="3.6 Integration in Xcode (Unity)">
        This section will guide you on how to integrate SDK **in Xcode level** (no code changes in Xcode).

        Reference sample: `unity_xcode_sample_app`

        *Use this path if you want to integrate Bright SDK at the Xcode level for a Unity project. If you already completed Step 3.5, skip this section.*

        Unity generates an Xcode project when building for iOS. The default template passes app lifecycle control to `UnityFramework` immediately after launch. Bright SDK must show the consent screen **before** the game launches, so your app must initialize the root view controller, show consent, and only then pass control to `UnityFramework`.

        Use `unity_xcode_sample_app` as reference. This is based on Unity's official documentation for integrating Unity as a library into a standard iOS app, simplified to the minimum steps needed for Bright SDK.

        <Tip>
          If you have other 3rd-party frameworks that need to initialize before your game launches, consider using Step 3.5 (Unity Editor integration) instead.
        </Tip>

        **<u>3.6.1 Embed the Bright SDK Framework</u>**

        1. Follow [Step 3.1](https://docs.bright-sdk.com/integration-guides/ios-tvos#:~:text=3.1%20Embedding%20the%20Framework%20in%20Xcode) for the main app target.
        2. Additionally, link `brdsdk.xcframework` with `UnityFramework`:

           * In **Project Navigator**, select the project → select **UnityFramework** under Targets.
           * Go to **Build Phases** → expand **Link Binary With Libraries.**
           * Click **+**, select `brdsdk.xcframework`, click **Add.**

                   <img src="https://mintcdn.com/brightdata-31a14106/pkPzFIQJLdPO3rSx/integration-guides/image/tvOS_Integrate_Bright_SDK_3.png?fit=max&auto=format&n=pkPzFIQJLdPO3rSx&q=85&s=bb88f1554b550e4410c4383c4de22a0d" alt="Build Phases Link Binary" width="600" data-path="integration-guides/image/tvOS_Integrate_Bright_SDK_3.png" />

        **<u>3.6.2 Embed the SDK Dialog in Your Code</u>**

        <img src="https://mintcdn.com/brightdata-31a14106/pkPzFIQJLdPO3rSx/integration-guides/image/tvOS_Integrate_Bright_SDK_4.png?fit=max&auto=format&n=pkPzFIQJLdPO3rSx&q=85&s=4f901fbb7f991faca6994cae4def1030" alt="Consent UI Mockup" width="300" data-path="integration-guides/image/tvOS_Integrate_Bright_SDK_4.png" />

        Using `unity_xcode_sample_app` as a reference:

        1. Copy the contents of `unity_xcode_sample_app/main/main.m` into `MainApp/main.mm` of your Unity project.

        2. Open `MainApp/main.mm` and locate `loadBrightFramework` - set appropriate button titles for the consent screen:

           ```objective-c theme={null}
           agree_btn:"PeerTextREMOVE_ADS"
           disagree_btn: "NotPeerTextADS"
           ```

        3. If you offer ads as a monetization fallback, locate `loadUnityFramework` and enable your ad platform:

           ```objective-c theme={null}
           if (useMonetizationFallback) {
               // TODO: user did not agree to share resources with BrightData
               // set up showing advertisements instead
           ```

        4. Embed the `Data` folder into `UnityFramework.framework`:

           * Select the `Data` folder in **Project Navigator.**
           * In the **Inspector** pane (right side), find **Target Membership.**
           * Move the checkbox to the `UnityFramework` target.

                   <img src="https://mintcdn.com/brightdata-31a14106/pkPzFIQJLdPO3rSx/integration-guides/image/tvOS_Integrate_Bright_SDK_5.png?fit=max&auto=format&n=pkPzFIQJLdPO3rSx&q=85&s=3aa668c9f6f1be6978833870f5977dd7" alt="Target Membership Checkbox" width="400" data-path="integration-guides/image/tvOS_Integrate_Bright_SDK_5.png" />
      </Step>
    </Steps>
  </Step>

  <Step title="Add Opt-In/Out Settings Option" titleSize="h3">
    <OptInOut platform="ios" />
  </Step>

  <Step title="Custom Consent Screen (optional)" titleSize="h3">
    <CustomConsentApple platform="ios" />
  </Step>

  <Step title="App Performance" titleSize="h3">
    We prioritize user experience. Ensure your app maintains good performance.

    Performance Guidelines:

    1. ✅ No input lag - ensure responsive UI interactions.
    2. ✅ Average CPU load: ≤ 50%.
    3. ✅ RAM usage: ≤ 90%.

    <Note>
      **Important:** If system load is too high, we cannot use the device's free resources. Such devices will not be counted as active and will not generate revenue.
    </Note>
  </Step>

  <Step title="Build & Run Your App" titleSize="h3">
    **Native iOS / tvOS** - Use Xcode to build and run your app. Ensure New Build System is selected under File → Project Settings.

    **Unity After generating the Xcode project**

    1. Select the main project scheme.
    2. Connect your iPhone/Apple TV and select it as the target device.
    3. Configure Signing & Capabilities for the main target.
    4. Press Product → Run (⌘R).
  </Step>

  <Step title="Update Your Terms of Service" titleSize="h3">
    <Tos platform="ios" />
  </Step>

  <Step title="Submit Your Integration for Review" titleSize="h3">
    <SubmitIntegrationReview platform="ios" />
  </Step>

  <Step title="How to Update the SDK" titleSize="h3">
    <UpdateSDK platform="ios" />
  </Step>

  <Step title="API Documentation" titleSize="h3">
    <Steps>
      <Step title="Part 1: Unity Plugin" titleSize="h3">
        <AccordionGroup>
          <Accordion title="Class: BrdsdkBridge">
            **Constants:**

            | Constant           | Description                           |
            | :----------------- | :------------------------------------ |
            | `CHOICE_NONE`      | Consent screen has not yet been shown |
            | `CHOICE_AGREED`    | User accepted the consent screen      |
            | `CHOICE_DISAGREED` | User declined the consent screen      |

            **Methods:**

            | Method                                                     | Returns               | Description                                                                                                                                                                         |
            | :--------------------------------------------------------- | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
            | `init(...)`                                                | `void`                | Initializes the SDK. Must be called at app startup. All other methods are accessible after successful initialization.                                                               |
            | `opt_out()`                                                | `void`                | Disables Bright SDK (e.g. from Settings screen)                                                                                                                                     |
            | `enqueue_opt_out()`                                        | `void`                | Enqueues an opt-out action to be executed once the SDK is loaded and configured                                                                                                     |
            | `external_opt_in()`                                        | `bool`                | Opts in and starts the Bright SDK process if permitted. ⚠️ NOT allowed by default — always use `show_consent()` or consult Bright Data first. Returns `true` if permitted.          |
            | `enqueue_external_opt_in()`                                | `void`                | Enqueues an opt-in action once SDK is loaded. Checks authorization status before and after enqueueing.                                                                              |
            | `show_consent(benefit, agree_btn, disagree_btn, language)` | `bool`                | Shows the consent screen (e.g. when user toggles Settings switch to enable SDK)                                                                                                     |
            | `get_choice()`                                             | `int`                 | Returns the user's current choice                                                                                                                                                   |
            | `consent_shown()`                                          | `bool`                | Triggers post-actions when a custom consent screen is shown. Must be called when presenting a custom consent screen. Returns `false` if SDK authorization status is not Authorized. |
            | `authorize_device()`                                       | `AuthorizationStatus` | Checks SDK availability on the device. Required before showing a custom consent screen; optional otherwise.                                                                         |
            | `get_uuid()`                                               | `string`              | Returns the current SDK UUID, or `null` if SDK is not initialized                                                                                                                   |
            | `set_on_sdk_ready_callback(callback)`                      | `void`                | Sets a handler for when the SDK is configured and ready                                                                                                                             |
            | `set_on_consent_presented_callback(callback)`              | `void`                | Sets a handler for when the consent screen is presented                                                                                                                             |
            | `set_on_consent_closed_callback(callback)`                 | `void`                | Sets a handler for when the consent screen is dismissed (via close, agree, or disagree)                                                                                             |
          </Accordion>

          <Accordion title="Method Details">
            **`init()`** Initializes the SDK. Must be called at app startup. All other methods are accessible after successful initialization. Consent screen is shown on first initialization by default - skip by setting `skip_consent: true`.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void init(
                string benefit,
                string agree_btn,
                string disagree_btn,
                string opt_out_instructions,
                string appicon,
                ChoiceCallback on_choice_callback,
                bool skip_consent = false,
                string language = null,
                ConsentColors colors = null,
                ConsentBackgroundImage background_image = null,
                ConsentActionInfo opt_in_info = null,
                ConsentActionInfo opt_out_info = null,
                ConsentFontsInfo fonts = null,
                string campaign = null
            )
            ```

            | Parameter              | Type                      | Description                                                |
            | :--------------------- | :------------------------ | :--------------------------------------------------------- |
            | `benefit`              | `string?`                 | Benefit text shown on the consent screen                   |
            | `agree_btn`            | `string`                  | "Agree" button text                                        |
            | `disagree_btn`         | `string`                  | "Disagree" button text                                     |
            | `opt_out_instructions` | `string?`                 | Instructions for opting out                                |
            | `appicon`              | `string?`                 | xcassets name or path of the icon image                    |
            | `on_choice_callback`   | `ChoiceCallback`          | Callback method reference                                  |
            | `skip_consent`         | `bool`                    | Skip consent screen on init; show later via `show_consent` |
            | `language`             | `string?`                 | Preferred language (see supported values below)            |
            | `colors`               | `ConsentColors?`          | Consent screen colors                                      |
            | `background_image`     | `ConsentBackgroundImage?` | Background images for consent screen                       |
            | `opt_in_info`          | `ConsentActionInfo?`      | Opt-in button customization                                |
            | `opt_out_info`         | `ConsentActionInfo?`      | Opt-out button customization                               |
            | `fonts`                | `ConsentFontsInfo?`       | Font overrides for consent screen                          |
            | `campaign`             | `string?`                 | Campaign name                                              |

            **Supported language values:** `ar_SA`, `de-DE`, `en-US`, `es-ES`, `fa-AF`, `fr-FR`, `he-IL`, `hi-IN`, `it-IT`, `ja-JP`, `ko-KR`, `ms-MY`, `nl-NL`, `pt-PT`, `ro-RO`, `ru-RU`, `th`, `tr-TR`, `vi-VN`, `zh-CN`, `zh-TW`

            **`opt_out()`** Disables Bright SDK (e.g. from Settings screen).

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void opt_out()
            ```

            **`enqueue_opt_out()`** Enqueues an opt-out action to be executed once the SDK is loaded and configured.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void enqueue_opt_out()
            ```

            **`external_opt_in()`** Opts in and starts the Bright SDK process if permitted.

            <Warning>
              **NOT allowed by default.** Always use `show_consent()` or consult Bright Data first.
            </Warning>

            Returns `true` if the operation is permitted by the authorization device.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static bool external_opt_in()
            ```

            **`enqueue_external_opt_in()`** Enqueues an opt-in action to be executed once the SDK is loaded and configured. Also checks authorization status before and after enqueueing.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void enqueue_external_opt_in()
            ```

            **`show_consent()`** Shows the consent screen (e.g. when the user toggles the Settings switch to enable SDK).

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static bool show_consent(string benefit, string agree_btn, string disagree_btn, string language)
            ```

            **`get_choice()`** Returns the user's current choice.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static int get_choice()
            ```

            **`consent_shown()`** Triggers post-actions when a custom consent screen is shown. Must be called when presenting a custom consent screen. Returns `false` if SDK authorization status is not Authorized.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static bool consent_shown()
            ```

            **`authorize_device()`** Checks SDK availability on the device. Required before showing a custom consent screen; optional otherwise.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static BrdsdkBridge.AuthorizationStatus authorize_device()
            ```

            **`get_uuid()`** Returns the current SDK UUID, or `null` if SDK is not initialized.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static string get_uuid()
            ```

            **`set_on_sdk_ready_callback()`** Sets a handler for when the SDK is configured and ready.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void set_on_sdk_ready_callback(EmptyCallback callback)
            ```

            **`set_on_consent_presented_callback()`** Sets a handler for when the consent screen is presented.

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void set_on_consent_presented_callback(EmptyCallback callback)
            ```

            **`set_on_consent_closed_callback()`** Sets a handler for when the consent screen is dismissed (via close, agree, or disagree).

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            static void set_on_consent_closed_callback(EmptyCallback callback)
            ```
          </Accordion>

          <Accordion title="Enums & Classes (Unity)">
            **Enum: `BrdsdkBridge.AuthorizationStatus`**

            | Value                  | Description                                                                          |
            | :--------------------- | :----------------------------------------------------------------------------------- |
            | `Authorized`           | SDK can be used with either SDK's or custom consent screen                           |
            | `SDKNotInitialized`    | SDK has not been initialized                                                         |
            | `ParentControlEnabled` | Parental controls are enabled — do not use SDK                                       |
            | `OnlySDKConsent`       | Only the SDK's built-in consent screen may be used; `external_opt_in` is not allowed |
            | `PlatformNotSupported` | Authorization method called on unsupported platform                                  |

            **Class: `ConsentColors`**

            | Property               | Type    | Description                     |
            | :--------------------- | :------ | :------------------------------ |
            | `backgroundColor`      | `Int32` | Consent window background color |
            | `titleColor`           | `Int32` | Title text color                |
            | `consentMessageColor`  | `Int32` | Main message text color         |
            | `consentLinksColor`    | `Int32` | Main message link color         |
            | `privacyColor`         | `Int32` | Privacy/license text color      |
            | `privacyLinksColor`    | `Int32` | Privacy/license link color      |
            | `iconsForegroundColor` | `Int32` | Icon foreground color           |
            | `iconsBackgroundColor` | `Int32` | Icon background color           |

            **Class: `ConsentBackgroundImage`**

            | Property         | Type                               | Description                                                                    |
            | :--------------- | :--------------------------------- | :----------------------------------------------------------------------------- |
            | `portraitImage`  | `String`                           | xcassets name or file path for portrait image                                  |
            | `landscapeImage` | `String?`                          | xcassets name or file path for landscape image. Falls back to portrait if null |
            | `scaleMode`      | `ConsentBackgroundImage.ScaleMode` | Scale mode for the image view                                                  |

            **Enum: `ConsentBackgroundImage.ScaleMode`**

            | Value             | Description                                                     |
            | :---------------- | :-------------------------------------------------------------- |
            | `ScaleToFill`     | Scales to fill, may change aspect ratio                         |
            | `ScaleAspectFit`  | Scales to fit, maintains aspect ratio, transparent areas remain |
            | `ScaleAspectFill` | Scales to fill, maintains aspect ratio, may clip content        |

            **Class: `ConsentActionInfo`**

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            public ConsentActionInfo(
                string _backgroundImage,
                string _textImage,
                Int32? _backgroundColor,
                Int32? _textColor
            )
            ```

            | Parameter          | Type      | Description                                                                 |
            | :----------------- | :-------- | :-------------------------------------------------------------------------- |
            | `_backgroundImage` | `string?` | Path or xcassets name for button background. Uses `backgroundColor` if null |
            | `_textImage`       | `string?` | Path or xcassets name for button title image. Uses `textColor` if null      |
            | `_backgroundColor` | `Int32?`  | Button background color                                                     |
            | `_textColor`       | `Int32?`  | Button text color                                                           |

            | Property      | Type          | Description               |
            | :------------ | :------------ | :------------------------ |
            | `titleText`   | `ConsentFont` | Font for consent title    |
            | `mainText`    | `ConsentFont` | Font for main description |
            | `licenseText` | `ConsentFont` | Font for license text     |
            | `iconsText`   | `ConsentFont` | Font for under-icon texts |
            | `buttonsText` | `ConsentFont` | Font for button texts     |

            **Class: `ConsentFontsInfo.ConsentFont`**

            ```csharp theme={null} theme={null} theme={null} theme={null} theme={null}
            public ConsentFont(string _nameOrPath, float _size)
            ```

            | Parameter     | Type     | Description                               |
            | :------------ | :------- | :---------------------------------------- |
            | `_nameOrPath` | `string` | Registered font name or path to font file |
            | `size`        | `float`  | Font size                                 |
          </Accordion>
        </AccordionGroup>
      </Step>

      <Step title="Part 2: Swift / Objective-C" titleSize="h3">
        <Info>
          The APIs are identical for Swift and Objective-C - they differ in syntax only. For Objective-C, the `init` call must be made on a `brd_api` instance: `[[brd_api alloc] init...]`
        </Info>

        <AccordionGroup>
          <Accordion title="Class: brd_api">
            **Properties:**

            | Property             | Type            | Description                              |
            | :------------------- | :-------------- | :--------------------------------------- |
            | `onConsentPresented` | `(() -> Void)?` | Handler when consent screen is presented |
            | `onConsentClosed`    | `(() -> Void)?` | Handler when consent screen is dismissed |
            | `onSDKReady`         | `(() -> Void)?` | Handler when SDK is configured and ready |

            **Methods:**

            | Method                                                     | Returns               | Description                                                                                                                                                               |
            | :--------------------------------------------------------- | :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
            | `init(...)`                                                | —                     | Initializes the SDK. Throws `brd_api.api_error`.                                                                                                                          |
            | `opt_out()`                                                | `void`                | Disables Bright SDK (e.g. from Settings screen)                                                                                                                           |
            | `enqueue_opt_out()`                                        | `void`                | Enqueues opt-out to be executed once SDK is loaded and configured                                                                                                         |
            | `external_opt_in()`                                        | `Bool`                | Opts in and starts the Bright SDK process if permitted. ⚠️ NOT allowed by default — always use `show_consent()` or consult Bright Data first. Throws `brd_api.api_error`. |
            | `enqueue_external_opt_in()`                                | `void`                | Enqueues opt-in action once SDK is loaded. Checks authorization status before and after enqueueing.                                                                       |
            | `show_consent(_:benefit:agree_btn:disagree_btn:language:)` | `Bool`                | Shows the consent screen. Returns `true` if SDK is initialized and child control is disabled. Result delivered via `on_choice_change` callback.                           |
            | `get_choice()`                                             | `Int`                 | Returns the user's current choice                                                                                                                                         |
            | `consent_shown()`                                          | `Bool`                | Triggers post-actions when a custom consent screen is shown. Returns `false` if authorization status is not authorized.                                                   |
            | `authorizeDevice()`                                        | `AuthorizationStatus` | Checks SDK availability. Required before showing a custom consent screen; optional otherwise.                                                                             |
            | `get_uuid()`                                               | `String?`             | Returns current SDK UUID, or `nil` if SDK is not initialized                                                                                                              |
          </Accordion>

          <Accordion title="Method Details">
            **`init()`** Initializes the SDK. Throws `brd_api.api_error`.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            init(
                benefit: String? = nil,
                agree_btn: String? = nil,       // Default: "I Agree"
                disagree_btn: String? = nil,    // Default: "I Disagree"
                opt_out_instructions: String? = nil,
                appicon: UIImage? = nil,
                cwd _cwd: URL? = nil,
                sys_app_id: String? = nil,
                language: String? = nil,
                colors: ColorSettings? = nil,
                background_image: ConsentBackgroundImage? = nil,
                opt_in_info: ConsentActionInfo? = nil,
                opt_out_info: ConsentActionInfo? = nil,
                fonts: ConsentFontsInfo? = nil,
                skip_consent: Bool,
                campaign: String?,
                on_choice_change: ((Int)->Void)? = nil
            ) throws
            ```

            | Parameter              | Type                      | Description                                             |
            | :--------------------- | :------------------------ | :------------------------------------------------------ |
            | `benefit`              | `String?`                 | Benefit text prefix. Default: `"To support <app_name>"` |
            | `agree_btn`            | `String?`                 | "Agree" button text. Default: `"I Agree"`               |
            | `disagree_btn`         | `String?`                 | "Disagree" button text. Default: `"I Disagree"`         |
            | `opt_out_instructions` | `String?`                 | Opt-out instructions text                               |
            | `appicon`              | `UIImage?`                | Icon image for consent screen                           |
            | `language`             | `String?`                 | Preferred language (same values as Unity — see above)   |
            | `colors`               | `ColorSettings?`          | Color settings for consent screen                       |
            | `background_image`     | `ConsentBackgroundImage?` | Background images for consent screen                    |
            | `opt_in_info`          | `ConsentActionInfo?`      | Opt-in button customization                             |
            | `opt_out_info`         | `ConsentActionInfo?`      | Opt-out button customization                            |
            | `fonts`                | `ConsentFontsInfo?`       | Font overrides                                          |
            | `skip_consent`         | `Bool`                    | Skip consent on init; show later via `show_consent`     |
            | `campaign`             | `String?`                 | Campaign name                                           |
            | `on_choice_change`     | `((Int)->Void)?`          | Callback for choice updates                             |

            **`opt_out()`** Disables Bright SDK (e.g. from Settings screen).

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func opt_out()
            ```

            **`enqueue_opt_out()`** Enqueues opt-out to be executed once the SDK is loaded and configured.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func enqueue_opt_out()
            ```

            **`external_opt_in()`** Opts in and starts the Bright SDK process if permitted.

            <Warning>
              **NOT allowed by default.** Always use `show_consent()` or consult Bright Data first.
            </Warning>

            Returns `true` if permitted. Throws `brd_api.api_error`.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            public static func external_opt_in() throws
            ```

            **`enqueue_external_opt_in()`** Enqueues opt-in action once the SDK is loaded. Checks authorization status before and after enqueueing.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func enqueue_external_opt_in()
            ```

            **`show_consent()`** Shows the consent screen (e.g. when user activates the Settings toggle). Returns `true` if SDK is initialized and child control is disabled. Result delivered via `on_choice_change` callback.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func show_consent(_ parent: UIViewController?, benefit: String?,
                                     agree_btn: String?, disagree_btn: String?, language: String?) -> Bool
            ```

            **`get_choice()`** Returns the user's current choice.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func get_choice() -> Int
            ```

            **`consent_shown()`** Triggers post-actions when a custom consent screen is shown. Must be called when presenting a custom consent screen. Returns `false` if authorization status is not authorized.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func consent_shown() -> Bool
            ```

            **`authorizeDevice()`** Checks SDK availability. Required before showing a custom consent screen; optional otherwise.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func authorizeDevice() -> AuthorizationStatus
            ```

            **Usage example:**

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            let authStatus = brd_api.authorizeDevice()

            switch authStatus {
                case .sdkNotInitialized:     break // initialize SDK first
                case .parentControlEnabled:  break // do not use SDK
                case .authorized:
                    if Feature.customConsent {
                        // show your own consent screen
                    } else {
                        fallthrough // show SDK's consent screen
                    }
            }
            ```

            **`get_uuid()`** Returns current SDK UUID, or `nil` if SDK is not initialized.

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            static func get_uuid() -> String?
            ```
          </Accordion>

          <Accordion title="Enums & Classes (Swift / Obj-C)">
            **Enum: `Choice`**

            | Value     | Description                           |
            | :-------- | :------------------------------------ |
            | `none`    | Consent screen has not yet been shown |
            | `peer`    | User accepted the consent screen      |
            | `notPeer` | User declined the consent screen      |

            **Enum: `brd_api.AuthorizationStatus`**

            | Value                  | Description                                                |
            | :--------------------- | :--------------------------------------------------------- |
            | `Authorized`           | SDK can be used with either SDK's or custom consent screen |
            | `SDKNotInitialized`    | SDK has not been initialized                               |
            | `ParentControlEnabled` | Parental controls are enabled - do not use SDK             |
            | `PlatformNotSupported` | Authorization method called on unsupported platform        |

            **Enum: `brd_api.api_error`**

            | Case                     | Description                                                         |
            | :----------------------- | :------------------------------------------------------------------ |
            | `init_error(String)`     | Non-categorized initialization error                                |
            | `opt_in_not_allowed`     | Calling `*opt_in` is not allowed — use SDK's consent screen instead |
            | `sdk_not_initialized`    | Method called before SDK was initialized                            |
            | `enabled_parent_control` | Parental controls enabled — do not use SDK                          |

            **Class: `ConsentBackgroundImage`**

            | Property         | Type                 | Description                     |
            | :--------------- | :------------------- | :------------------------------ |
            | `portraitImage`  | `UIImage`            | Image for portrait orientation  |
            | `landscapeImage` | `UIImage`            | Image for landscape orientation |
            | `scaleMode`      | `UIView.ContentMode` | Scale mode for image view       |

            **Constructors:**

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            // With UIImage instances:
            init(portrait: UIImage, landscape: UIImage? = nil, scaleMode: UIView.ContentMode = .scaleAspectFill)

            // With xcassets names:
            init?(portraitName: String, landscapeName: String? = nil, scaleMode: UIView.ContentMode = .scaleAspectFill, in bundle: Bundle = .main)
            ```

            | Parameter                     | Type                   | Description                                                     |
            | :---------------------------- | :--------------------- | :-------------------------------------------------------------- |
            | `portrait` / `portraitName`   | `UIImage` / `String`   | Portrait image or xcassets name                                 |
            | `landscape` / `landscapeName` | `UIImage?` / `String?` | Landscape image or xcassets name. Falls back to portrait if nil |
            | `scaleMode`                   | `UIView.ContentMode`   | Scale mode. Use `.scaleAspectFit` or `.scaleAspectFill`         |
            | `bundle`                      | `Bundle`               | Bundle containing xcassets                                      |

            **Class: `ConsentActionInfo`**

            | Property          | Type       | Description                                                         |
            | :---------------- | :--------- | :------------------------------------------------------------------ |
            | `backgroundImage` | `UIImage?` | Button background image. Uses background color if nil               |
            | `textImage`       | `UIImage?` | Button title image. Uses title text if nil                          |
            | `backgroundColor` | `UIColor?` | Background color. Falls back to `ColorSettings.button_color` if nil |
            | `textColor`       | `UIColor?` | Text color. Falls back to `ColorSettings.button_color` if nil       |

            **Constructors:**

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            // With UIImage instances:
            init(backgroundImage: UIImage? = nil, textImage: UIImage? = nil, backgroundColor: UIColor? = nil, textColor: UIColor? = nil)

            // With xcassets names:
            init(backgroundName: String?, textName: String? = nil, in bundle: Bundle = .main)
            ```

            **Class: `ColorSettings`**

            | Property                 | Type       | Description                            |
            | :----------------------- | :--------- | :------------------------------------- |
            | `background_color`       | `UIColor?` | Consent window background color        |
            | `title_color`            | `UIColor?` | Title text color                       |
            | `consent_text_color`     | `UIColor?` | Main message text color                |
            | `consent_links_color`    | `UIColor?` | Main message link color                |
            | `privacy_text_color`     | `UIColor?` | Privacy/license text color             |
            | `privacy_links_color`    | `UIColor?` | Privacy/license link color             |
            | `qr_foreground_color`    | `UIColor?` | QR code foreground color *(tvOS only)* |
            | `qr_background_color`    | `UIColor?` | QR code background color *(tvOS only)* |
            | `icons_foreground_color` | `UIColor?` | Icon foreground color                  |
            | `icons_background_color` | `UIColor?` | Icon background color                  |

            **Constructor:**

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            init(background_color: UIColor? = nil, title_color: UIColor? = nil,
                 consent_text_color: UIColor? = nil, consent_links_color: UIColor? = nil,
                 privacy_text_color: UIColor? = nil, privacy_links_color: UIColor? = nil,
                 qr_foreground_color: UIColor? = nil, qr_background_color: UIColor? = nil,
                 icons_foreground_color: UIColor? = nil, icons_background_color: UIColor? = nil)
            ```

            | Property      | Type      | Description                |
            | :------------ | :-------- | :------------------------- |
            | `titleText`   | `UIFont?` | Font for consent title     |
            | `mainText`    | `UIFont?` | Font for main descriptions |
            | `licenseText` | `UIFont?` | Font for license text      |
            | `iconsText`   | `UIFont?` | Font for under-icon texts  |
            | `buttonsText` | `UIFont?` | Font for button texts      |

            **Constructor:**

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            init(titleText: UIFont? = nil, mainText: UIFont? = nil,
                 licenseText: UIFont? = nil, iconsText: UIFont? = nil,
                 buttonsText: UIFont? = nil)
            ```

            **Instance Methods** *(all return `Self` for chaining; all warn on invalid font; all subject to SDK size limits):*

            | Method                                 | Description                                         |
            | :------------------------------------- | :-------------------------------------------------- |
            | `setTitleText(withNameOrPath:size:)`   | Override title font by name or file path            |
            | `setMainText(withNameOrPath:size:)`    | Override main text font by name or file path        |
            | `setLicenseText(withNameOrPath:size:)` | Override license text font by name or file path     |
            | `setIconsText(withNameOrPath:size:)`   | Override under-icons text font by name or file path |
            | `setButtonsText(withNameOrPath:size:)` | Override buttons font by name or file path          |

            **Method signature:**

            ```swift theme={null} theme={null} theme={null} theme={null} theme={null}
            func set<Element>Text(withNameOrPath nameOrPath: String, size: CGFloat) -> Self
            ```
          </Accordion>
        </AccordionGroup>
      </Step>
    </Steps>
  </Step>
</Steps>
