> ## Documentation Index
> Fetch the complete documentation index at: https://help.airbridge.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Web SDK

## Install SDK

Install the Airbridge Web SDK using one of the methods below.

<AccordionGroup>
  <Accordion title="Load from the browser directly">
    Add the code below to the bottom of the `<head>` section.

    ```html lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    <script>
    (function(a_,i_,r_,_b,_r,_i,_d,_g,_e){function q(b,a){function d(){var l=x(b,a);y(l)}if(0<_g){var e,f=new (null!=(e=a_.XDomainRequest)?e:a_.XMLHttpRequest);e=function(){};f.open("GET",a);f.timeout=_g;f.onload=d;f.onerror=e;f.onprogress=e;f.ontimeout=e;f.send()}else d()}function y(b){if("complete"===i_.readyState)i_.head.appendChild(b);else{var a=function(){a_.removeEventListener("load",a);i_.head.appendChild(b)};a_.addEventListener("load",a)}}function x(b,a){var d=i_.createElement(r_);d.async=!0;d.src=a;d.onerror=function(){return z(b)};return d}function z(b){b.queue.filter(function(a){return 0<=_d.indexOf(a[0])}).forEach(function(a){a=a[1];a=a[a.length-1];"function"===typeof a&&a("Failed to load Airbridge SDK.")})}function r(b){var a={queue:null!=b?b:[],get isSDKEnabled(){return!1}};_i.concat(_d).forEach(function(d){var e=d.split("."),f=e.pop();e.reduce(function(l,t){var u;return l[t]=null!=(u=l[t])?u:{}},a)[f]=function(){a.queue.push([d,arguments])}});return a}null!=a_.__AIRBRIDGE__||(a_.__AIRBRIDGE__={mocks:[]});"undefined"!==typeof i_.documentMode&&(_r=_r.replace(/^https:/,""));a_.createAirbridge=function(){var b=r(),a;null==(a=a_.__AIRBRIDGE__)||a.mocks.push(b);q(b,_r);return b};a_[_b]||(_e=r(_e),a_[_b]=_e,q(_e,_r))})(window,document,"script","airbridge","https://static.airbridge.io/sdk/latest/airbridge.min.js","init startTracking stopTracking openBanner setBanner setDownload setDownloads openDeeplink setDeeplinks sendWeb setUserAgent setMobileAppData setUserID clearUserID setUserEmail clearUserEmail setUserPhone clearUserPhone setUserAttribute removeUserAttribute clearUserAttributes setUserAlias removeUserAlias clearUserAlias clearUser setUserId setUserAttributes addUserAlias setDeviceAlias removeDeviceAlias clearDeviceAlias setDeviceIFV setDeviceIFA setDeviceGAID events.send events.signIn events.signUp events.signOut events.purchased events.addedToCart events.productDetailsViewEvent events.homeViewEvent events.productListViewEvent events.searchResultViewEvent".split(" "),["events.wait","fetchResource","createTouchpoint","createTrackingLink"],0);

    airbridge.init({
        app: '<YOUR_APP_NAME>',
        webToken: '<YOUR_WEB_TOKEN>',
    })
    </script>
    ```
  </Accordion>

  <Accordion title="Install using the package manager">
    Run the commands below to install `airbridge-web-sdk-loader`.

    <CodeGroup>
      ```bash npm lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      npm install airbridge-web-sdk-loader
      ```

      ```bash yarn lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      yarn add airbridge-web-sdk-loader
      ```

      ```bash pnpm lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      pnpm i airbridge-web-sdk-loader
      ```
    </CodeGroup>

    If you install the `airbridge-web-sdk-loader` package, you can refer to the code below.

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import airbridge from 'airbridge-web-sdk-loader'

    airbridge.init({
        app: '<YOUR_APP_NAME>',
        webToken: '<YOUR_WEB_TOKEN>',
    })
    ```

    The `app` and `webToken` can be found in the Airbridge dashboard under **Settings → Tokens**.
  </Accordion>
</AccordionGroup>

### Supported browser

The Airbridge Web SDK works on all browsers that support ES5.

| Browser           | Supported |
| ----------------- | --------- |
| Chrome            | ✔️        |
| Firefox           | ✔️        |
| Safari            | ✔️        |
| Internet Explorer | IE 9 +    |

### SDK initialization

Initialize the Airbridge Web SDK using the `airbridge.init()` function. The `app` and `webToken` values required for initialization can be found in the Airbridge dashboard under **Settings → Tokens**. Additional initialization options can be configured as needed.

The following is the type definition for the initialization settings.

```typescript JavaScript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
interface InitializeOptions {
    app: string
    webToken: string
    autoStartTrackingEnabled?: boolean
    utmParsing?: boolean
    utmParameterValueReplaceMap?: Record<string, Record<string, string>>
    urlQueryMapping?: Record<string, string>
    userHash?: boolean
    cookieWindow?: number
    cookieWindowInMinutes?: number
    useProtectedAttributionWindow?: boolean
    protectedAttributionWindowInMinutes?: number
    shareCookieSubdomain?: boolean
    collectMolocoCookieID?: boolean
}
```

<Accordion title="SDK initialization options">
  ### Web SDK Options

  | **Option**                            | **Required or Optional** | **Type**  | **Default value** | **Description**                                                                                                                                                                                               |
  | ------------------------------------- | ------------------------ | --------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `app`                                 | Required                 | `string`  | `-`               | The app name that is required for the Web SDK initialization.                                                                                                                                                 |
  | `webToken`                            | Required                 | `string`  | `-`               | The Web SDK token that is required for the Web SDK initialization.                                                                                                                                            |
  | `autoStartTrackingEnabled`            | Optional                 | `boolean` | `true`            | If explicit opt-in is required, set this value to `false` and call `startTracking` manually.<br />For more details, refer to **Opt-in setup**.                                                                |
  | `utmParsing`                          | Optional                 | `boolean` | `false`           | Automatically maps UTM values from the URL parameters to the corresponding Airbridge campaign parameter values.<br />For more details, refer to **Set up campaign parameters**.                               |
  | `utmParameterValueReplaceMap`         | Optional                 | `object`  | `-`               | By configuring `utmParameterValueReplaceMap`, you can replace the values of UTM parameters collected through `utmParsing` with custom values.<br />For more details, refer to **Set up campaign parameters**. |
  | `urlQueryMapping`                     | Optional                 | `object`  | `-`               | When `urlQueryMapping` is used, `utmParsing` is ignored.<br />For more details, refer to **Set up campaign parameters**.                                                                                      |
  | `user`                                | Optional                 | `object`  | `-`               | You can pass user information during initialization.<br />For more details, refer to **Pass user data during initialization**.                                                                                |
  | `userHash`                            | Optional                 | `boolean` | `true`            | You can send user email addresses and phone numbers in hashed form.<br />For more details, refer to **Set up user properties**.                                                                               |
  | `cookieWindow`                        | Optional                 | `number`  | `3`               | For more information, refer to **Edit the attribution window**.                                                                                                                                               |
  | `cookieWindowInMinutes`               | Optional                 | `number`  | `-`               | For more information, refer to **Edit the attribution window**.                                                                                                                                               |
  | `useProtectedAttributionWindow`       | Optional                 | `boolean` | `true`            | For more information, refer to **Set the attribution window for web-to-app attribution**.                                                                                                                     |
  | `protectedAttributionWindowInMinutes` | Optional                 | `number`  | `30`              | For more information, refer to **Set the attribution window for web-to-app attribution**.                                                                                                                     |
  | `shareCookieSubdomain`                | Optional                 | `boolean` | `true`            | For more information, refer to **Share attribution data across subdomains**.                                                                                                                                  |
  | `collectMolocoCookieID`               | Optional                 | `boolean` | `false`           | This is an option for configuring the Moloco cookie ID. For more details, refer to **Collect Moloco cookie ID**.                                                                                              |
</Accordion>

### Verify Installation

Navigate to the page where the Airbridge Web SDK is installed, open the developer tools, and run the following code.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
console.log(airbridge.isSDKEnabled)
```

If `true` is printed after running the code above, the SDK has been installed and initialized successfully.

<Danger>
  **Attention**

  `airbridge.isSDKEnabled` is initially `false`. It changes to `true` once the Web SDK is fully loaded and initialized successfully.

  Depending on the network environment, loading may be delayed, and if checked before loading is complete, `false` may be returned.
</Danger>

If you suspect that `false` is being printed due to network delay, run the code below in the developer tools to check the value after 5 seconds.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
setTimeout(function () {
    console.log(airbridge.isSDKEnabled)
}, 5000)
```

### Opt-in setup

<Info>
  **Note**

  Optional setting. Configure only if necessary.
</Info>

The opt-in policy requires user consent before using user data.

After setting the `autoStartTrackingEnabled` to `false`, call the `startTracking` function at the point where you can collect events. When the `startTracking` function is called, the SDK will start collecting events.

The default setting is `true`.

1. Prevent automatic event tracking after initialization through the `autoStartTrackingEnabled`.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: 'YOUR_APP_NAME',
    webToken: 'YOUR_WEB_TOKEN',
    // ...
    autoStartTrackingEnabled: false,
})
```

2. Collect user responses to the collection and use of personal information. If the user agrees to the collection and use of personal information, start tracking events.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.startTracking()
```

### Opt-out setup

<Info>
  **Note**

  Optional setting. Configure only if necessary.
</Info>

The opt-out policy allows the use of user information until the user explicitly declines.

After setting the `autoStartTrackingEnabled` option to `true`, call the `stopTracking` function at the point where you can no longer collect events. When the `stopTracking` function is called, the SDK will stop collecting events.

1. Enable automatic event tracking after initialization through the `autoStartTrackingEnabled`. Since the default value of the `autoStartTrackingEnabled` option is true, events are tracked automatically event if this setting is omitted.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: 'YOUR_APP_NAME',
    webToken: 'YOUR_WEB_TOKEN',
    // ...
    autoStartTrackingEnabled: true,
})
```

2. Collect user responses to the collection and use of personal information. If the user refuses the collection and use of personal information, stop tracking events.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.stopTracking()
```

## Web Event

The Airbridge Web SDK collects user actions from the app as per settings and sends them as in-app events.

* [Understanding Events in Airbridge ](/en/guides/airbridge-event)

### Send web events

Use the `airbridge.events.send` function to send events.

Refer to the example below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.events.send('category', {
    label: 'Tool',
    action: 'Hammer',
    value: 10,
    semanticAttributes: {
        currency: 'USD',
        transactionID: 'transaction_123',
        products: [
            {
                productID: 'coke_zero',
                name: 'PlasticHammer',
            },
        ],
    },
    customAttributes: {
        promotion: 'FirstPurchasePromotion',
    },
})
```

| **Option**           | **Required or Optional** | **Type** | **Description**                  |
| -------------------- | ------------------------ | -------- | -------------------------------- |
| `category`           | Required                 | `string` | Name of the event                |
| `action`             | Optional                 | `string` | Subcategory of the event         |
| `label`              | Optional                 | `string` | Subcategory of the event         |
| `value`              | Optional                 | `number` | Subcategory of the event         |
| `semanticAttributes` | Optional                 | `object` | Semantic attributed of the event |
| `customAttributes`   | Optional                 | `object` | Custom attribute of the event    |

Refer to the component definition and available strings below.

<AccordionGroup>
  <Accordion title="Event Category">
    Airbridge provides Standard Events. Refer to the list of [Standard Events](/en/guides/airbridge-event-types#list-of-standard-events) and send events accordingly.

    You can send a custom event by entering the event name set in the [event taxonomy](/en/guides/airbridge-event-taxonomy).
  </Accordion>

  <Accordion title="Attributes">
    Additional information about the event can be collected using attributes.

    * `action`, `label`: Collect information that can be used as GroupBys in the Airbridge reports.
    * `value`: Collect information that can be used for sales analysis. Airbridge can perform calculations using the collected data.
    * Semantic Attribute: Collect predefined attributes by Airbridge.
    * Custom Attribute: Collect attributes defined by Airbridge users.

    The semantic attributes predefined by Airbridge can be found in the user guide below.

    * [List of semantic attributes](/en/guides/airbridge-event-elements#%EC%8B%9C%EB%A7%A8%ED%8B%B1-%EC%96%B4%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%8A%B8-%EB%AA%A9%EB%A1%9D)
  </Accordion>
</AccordionGroup>

### Additional web event settings

<Info>
  **Note**

  Optional setting. Configure only if necessary.
</Info>

Configure additional settings for sending web events if necessary.

<Accordion title="Device identifier setup">
  You can send additional user information when sending the events through the SDK.

  | **Function**                  | **Description**                    |
  | ----------------------------- | ---------------------------------- |
  | `airbridge.setDeviceAlias`    | Adds device identifier             |
  | `airbridge.removeDeviceAlias` | Delete specified device identifier |
  | `airbridge.clearDeviceAlias`  | Delete all device identifiers      |

  ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  airbridge.setDeviceAlias('<DEVICE_ALIAS_KEY>', '<DEVICE_ALIAS_VALUE>')
  airbridge.removeDeviceAlias('<DEVICE_ALIAS_KEY>')
  airbridge.clearDeviceAlias()
  ```
</Accordion>

### Example codes

Airbridge collects in-app events that are classified as Standard Events and Custom Events. Standard Events. are events predefined by Airbridge.

Refer to the example codes below.

<AccordionGroup>
  <Accordion title="Sign-up, Sign-in, Sign-out, Home Screen, Product Catalog">
    **Sign-up**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    // Make sure to set user information before sending the event
    airbridge.setUserID('string')
    airbridge.setUserPhone('string')
    airbridge.setUserEmail('string')
    airbridge.setUserAttribute('string', 'string')
    airbridge.setUserAlias('string', 'string')

    // Send event
    airbridge.events.send('airbridge.user.signup')
    ```

    **Sign-in**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    // Make sure to set user information before sending the event
    airbridge.setUserID('string')
    airbridge.setUserPhone('string')
    airbridge.setUserEmail('string')
    airbridge.setUserAttribute('string', 'string')
    airbridge.setUserAlias('string', 'string')

    // Send event
    airbridge.events.send('airbridge.user.signin')
    ```

    **Sign-out**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    // Send event before clearing user information
    airbridge.events.send('airbridge.user.signout')

    // Initialize user information
    airbridge.clearUser()
    ```

    **Home Screen**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.ecommerce.home.viewed')
    ```

    **Product Catalog**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.ecommerce.product.viewed', {
        semanticAttributes: {
            listID: '84e6e236-38c4-48db-9b49-16e4cc064386',
            currency: 'USD',
            products: [
                {
                    productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                    name: 'PlasticHammer',
                    price: 10,
                    quantity: 1,
                    currency: 'USD',
                },
                {
                    productID: 'd6ab2fbe-decc-4362-b719-d257a131e91e',
                    name: 'PlasticFork',
                    price: 1,
                    quantity: 1,
                    currency: 'USD',
                },
            ],
        },
    })
    ```
  </Accordion>

  <Accordion title="Search Results, Product View, Add Payment Info, Add to Wishlist, Add to Cart">
    **Search Results**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.ecommerce.searchResults.viewed', {
        semanticAttributes: {
            query: 'Plastic',
            currency: 'USD',
            products: [
                {
                    productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                    name: 'PlasticHammer',
                    price: 10,
                    quantity: 1,
                    currency: 'USD',
                },
                {
                    productID: 'd6ab2fbe-decc-4362-b719-d257a131e91e',
                    name: 'PlasticFork',
                    price: 1,
                    quantity: 1,
                    currency: 'USD',
                },
            ],
        },
    })
    ```

    **Product View**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.setUserID('string')
    airbridge.setUserPhone('string')
    airbridge.setUserEmail('string')
    airbridge.setUserAttribute('string', 'string')
    airbridge.setUserAlias('string', 'string')

    airbridge.events.send('airbridge.ecommerce.product.viewed', {
        semanticAttributes: {
            currency: 'USD',
            products: [{
                productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                name: 'PlasticHammer',
                price: 10,
                quantity: 1,
                currency: 'USD',
            }],
        },
    })
    ```

    **Add Payment Info**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.addPaymentInfo', {
        semanticAttributes: {
            type: 'CreditCard',
        },
    })
    ```

    **Add to Wishlist**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.addToWishlist', {
        semanticAttributes: {
            listID: '189a2f8b-83ee-4074-8158-726be54e57d4',
            currency: 'USD',
            products: [{
                productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                name: 'PlasticHammer',
                price: 10,
                quantity: 1,
                currency: 'USD',
            }],
        },
    })
    ```

    **Add to Cart**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.ecommerce.product.addedToCart', {
        semanticAttributes: {
            cartID: '421eaeb7-6e80-4694-933e-f2e1a55e9cbd',
            currency: 'USD',
            products: [{
                productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                name: 'PlasticHammer',
                price: 10,
                quantity: 1,
                currency: 'USD',
            }],
        },
    })
    ```
  </Accordion>

  <Accordion title="Initiate Checkout, Order Complete, Order Cancel, Start Trial, Subscribe, Unsubscribe">
    **Initiate Checkout**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.initiateCheckout', {
        semanticAttributes: {
            transactionID: '0a7ee1ec-33da-4ffb-b775-89e80e75978a',
            currency: 'USD',
            products: [
                {
                    productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                    name: 'PlasticHammer',
                    price: 10,
                    quantity: 1,
                    currency: 'USD',
                },
                {
                    productID: 'd6ab2fbe-decc-4362-b719-d257a131e91e',
                    name: 'PlasticFork',
                    price: 1,
                    quantity: 1,
                    currency: 'USD',
                },
            ],
        },
    })
    ```

    **Order Complete**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.ecommerce.order.completed', {
        value: 11,
        semanticAttributes: {
            transactionID: '8065ef16-162b-4a82-b683-e51aefdda7d5',
            currency: 'USD',
            inAppPurchased: true,
            products: [
                {
                    productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                    name: 'PlasticHammer',
                    price: 10,
                    quantity: 1,
                    currency: 'USD',
                },
                {
                    productID: 'd6ab2fbe-decc-4362-b719-d257a131e91e',
                    name: 'PlasticFork',
                    price: 1,
                    quantity: 1,
                    currency: 'USD',
                },
            ],
        },
    })
    ```

    **Order Cancel**

    <Danger>
      **Attention**

      For Order Cancel events, make sure to enter the `transactionID` of the Order Cancel event into the `transactionID` field.

      If the `transactionID` values don't match, the Order Cancel event won't be processed properly.

      For more details, refer to the [Collecting Order Cancel Events for Accurate Sales Performance Measurement](/en/guides/analyzing-real-purchase-performance).
    </Danger>

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.ecommerce.order.canceled', {
        value: 11,
        semanticAttributes: {
            transactionID: '8065ef16-162b-4a82-b683-e51aefdda7d5',
            currency: 'USD',
            inAppPurchased: true,
            products: [
                {
                    productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                    name: 'PlasticHammer',
                    price: 10,
                    quantity: 1,
                    currency: 'USD',
                },
                {
                    productID: 'd6ab2fbe-decc-4362-b719-d257a131e91e',
                    name: 'PlasticFork',
                    price: 1,
                    quantity: 1,
                    currency: 'USD',
                },
            ],
        },
    })
    ```

    **Start Trial**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.startTrial', {
        semanticAttributes: {
            transactionID: 'ef1e5271-0370-407c-b1e9-669a8df1dc2c',
            currency: 'USD',
            period: 'P1M',
            products: [{
                productID: '306a57cb-f653-4220-a208-8405d8e4d506',
                name: 'MusicStreamingMembership',
                price: 15,
                currency: 'USD',
            }],
        },
    })
    ```

    **Subscribe**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.subscribe', {
        value: 15,
        semanticAttributes: {
            currency: 'USD',
            transactionID: 'cbe718c7-e44e-4707-b5cd-4a6a29f29649',
            period: 'P1M',
            isRenewal: true,
            products: [{
                productID: '306a57cb-f653-4220-a208-8405d8e4d506',
                name: 'MusicStreamingMembership',
                price: 15,
                currency: 'USD',
            }],
        },
    })
    ```

    **Unsubscribe**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.unsubscribe', {
        value: 15,
        semanticAttributes: {
            currency: 'USD',
            transactionID: 'cbe718c7-e44e-4707-b5cd-4a6a29f29649',
            period: 'P1M',
            isRenewal: true,
            products: [{
                productID: '306a57cb-f653-4220-a208-8405d8e4d506',
                name: 'MusicStreamingMembership',
                price: 15,
                currency: 'USD',
            }],
        },
    })
    ```
  </Accordion>

  <Accordion title="Ad Impression, Ad Click, Complete Tutorial, Achieve Level, Unlock Achievement">
    **Ad Impression**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.adImpression', {
        value: 0.01,
        semanticAttributes: {
            adPartners: [{
                app_version: '5.18.0',
                adunit_id: '12345',
                adunit_name: '12345',
                adunit_format: 'Banner',
                id: '12345',
                currency: 'USD',
                publisher_revenue: 12345.123,
                adgroup_id: '12345',
                adgroup_name: '12345',
                adgroup_type: '12345',
                adgroup_priority: '12345',
                country: 'kr',
                precision: 'publisher_defined',
                network_name: '12345',
                network_placement_id: '12345',
                demand_partner_data: '12345',
            }],
        },
    })
    ```

    **Ad Click**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.adClick', {
        value: 0.1,
        semanticAttributes: {
            adPartners: [{
                app_version: '5.18.0',
                adunit_id: '12345',
                adunit_name: '12345',
                adunit_format: 'Banner',
                id: '12345',
                currency: 'USD',
                publisher_revenue: 12345.123,
                adgroup_id: '12345',
                adgroup_name: '12345',
                adgroup_type: '12345',
                adgroup_priority: '12345',
                country: 'kr',
                precision: 'publisher_defined',
                network_name: '12345',
                network_placement_id: '12345',
                demand_partner_data: '12345',
            }],
        },
    })
    ```

    **Complete Tutorial**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.completeTutorial', {
        semanticAttributes: {
            description: 'Finish Initial Tutorial',
        },
    })
    ```

    **Achieve Level**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.achieveLevel', {
        semanticAttributes: {
            level: 13,
        },
    })
    ```

    **Unlock Achievement**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.unlockAchievement', {
        semanticAttributes: {
            achievementID: '36a0f0bb-b153-4be1-a3e0-3cb5b2b076c1'
            description: 'Finish Initial Tutorial',
            score: 80,
        },
    })
    ```
  </Accordion>

  <Accordion title="Rate, Share, Schedule, Spend Credits">
    **Rate**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.rate', {
        semanticAttributes: {
            rateID: '531c64b3-4704-4780-a306-89014ec18daf',
            rate: 4.5,
            maxRate: 5,
            currency: 'USD',
            products: [{
                productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                name: 'PlasticHammer',
                price: 10,
                currency: 'USD',
            }],
        },
    })
    ```

    **Share**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.share', {
        semanticAttributes: {
            description: 'Share Promotion',
            sharedChannel: 'CopyLink',
        },
    })
    ```

    **Schedule**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.schedule', {
        semanticAttributes: {
            scheduleID: '75712915-2cd9-4e42-a85e-8d42f356f4c6',
            datetime: '2024-01-01T00:00:00+00:00',
            place: 'ConferenceRoom',
            products: [{
                productID: 'abb3e65d-17bc-4b28-89e3-5e356c0ea697',
                name: 'ConferenceRoom',
            }],
        },
    })
    ```

    **Spend Credits**

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.events.send('airbridge.spendCredits', {
        semanticAttributes: {
            transactionID: '22eb193d-be11-4fe4-95da-c91a196faf1c',
            currency: 'USD',
            products: [{
                productID: '0117b32a-5a6c-4d4c-b64c-7858e07dba78',
                name: 'PlasticHammer',
                price: 10,
                currency: 'USD',
            }],
        },
    })
    ```
  </Accordion>
</AccordionGroup>

Custom Events are events defined by Airbridge users to track user actions that are unique to their services.

Refer to the example code below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.events.send('category', {
    label: 'label',
    action: 'action',
    value: 10,
    semanticAttributes: {
        transactionID: 'transaction_123',
    },
    customAttributes: {
        key: 'value',
    }
})
```

## User Data

### Set up User ID

User IDs refer to the user identifier used in a service. User IDs should be unique IDs that can unique users across websites and apps.

The user data you set is stored in the browser’s local storage and will be included in all events **until it is cleared**.

| **Function**                | **Description**                                                                 |
| --------------------------- | ------------------------------------------------------------------------------- |
| `airbridge.setUserID`       | Inputs user ID.                                                                 |
| `airbridge.clearUserID`     | Deletes user ID.                                                                |
| `airbridge.setUserAlias`    | Inputs additional user identifier.                                              |
| `airbridge.removeUserAlias` | Deletes specified user identifier from the list of additional user identifiers. |
| `Airbridge.clearUserAlias`  | Deletes all additional user identifiers.                                        |

Refer to the example below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
// ID
airbridge.setUserID('testID')
airbridge.clearUserID()

// alias
airbridge.setUserAlias('ADD_YOUR_KEY', 'value')
airbridge.removeUserAlias('DELETE_THIS_KEY')
airbridge.clearUserAlias()
```

### Set up user properties

<Danger>
  **Attention**

  Sensitive user information may be included. Send after a thorough review with a legal advisor.
</Danger>

By setting user properties, you can send additional user information.

| **Function**                    | **Description**                                                              |
| ------------------------------- | ---------------------------------------------------------------------------- |
| `airbridge.setUserEmail`        | Inputs user’s email address that is hashed using SHA-256.                    |
| `airbridge.clearUserEmail`      | Deletes user email.                                                          |
| `airbridge.setUserPhone`        | Inputs user’s phone number that is hashed using SHA-256.                     |
| `airbridge.clearUserPhone`      | Deletes user’s phone number.                                                 |
| `airbridge.setUserAttribute`    | Inputs additional user property.                                             |
| `airbridge.removeUserAttribute` | Deletes specified user property from the list of additional user properties. |
| `airbridge.clearUserAttributes` | Deletes all additional user properties.                                      |

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
// Automatically hashed on client side using SHA256
// Can turn off hashing feature with special flag
airbridge.setUserEmail('testID@ab180.co')
airbridge.setUserPhone('821012341234')

// attributes
airbridge.setUserAttribute('ADD_YOUR_KEY', 1)
airbridge.setUserAttribute('ADD_YOUR_KEY', 1.0)
airbridge.setUserAttribute('ADD_YOUR_KEY', '1')
airbridge.setUserAttribute('ADD_YOUR_KEY', true)
airbridge.removeUserAttribute('DELETE_THIS_KEY')
airbridge.clearUserAttributes()
```

You can send user email addresses and phone numbers in hashed form.

The default setting is `true`.

The user ID is not affected by the hash option, so if hashing is required, you must hash the user ID yourself before assigning its value.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN?',
    // ...
    userHash: false, // Default true
})
```

### Clear user data

Use the `clearUser` function to clear user data.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.clearUser()
```

## Web-to-App Setup

The Airbridge Web SDK supports deep linking, which allows you to pass attribution data from the web to the app. It also enables passing attribution data from one web session to another, without involving an app.

### Create smart app banners

You can use the `openBanner` function to display a smart banner that encourages web users to install your app. By implementing various options, you can customize the banner’s title, description, button color and text, and enable **Web-to-App**, **Web-to-Store**, or **Web-to-Web** tracking.

<Frame>
  <img src="https://mintcdn.com/airbridge-help-center/NnPE_gJFbAXa7mQR/asset/image/ab180-blog-smart-banner.png?fit=max&auto=format&n=NnPE_gJFbAXa7mQR&q=85&s=a61a18f392af98c6f4cf7841ec5ea7af" alt="Web SDK Banner" width="750" height="400" data-path="asset/image/ab180-blog-smart-banner.png" />
</Frame>

**공통 옵션**

| **Option**    | **Required or Optional** | **Type**            | **Description**                                                                                                                                                                               |
| ------------- | ------------------------ | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`       | Required                 | `string`            | Banner name                                                                                                                                                                                   |
| `description` | Required                 | `string`            | Banner description                                                                                                                                                                            |
| `buttonText`  | Required                 | `string`            | The text to be displayed on the app download button in the banner                                                                                                                             |
| `color`       | Optional                 | `string`            | The color to be applied to the app download button in the banner. It can be set using a CSS color format.                                                                                     |
| `position`    | Optional                 | `'top' \| 'bottom'` | Specifies the position of the banner.<br />-<br />`top`<br />: The banner will appear at the top of the screen<br />-<br />`bottom`<br />: The banner will appear at the bottom of the screen |
| `destination` | Required                 | `object`            | Specifies how the app download button in the banner behaves.<br />The behavior varies depending on the selected<br />`type`<br />.                                                            |
| `styles`      | Optional                 | `object`            | Custom styles to be applied to the banner                                                                                                                                                     |

#### Web-to-App setup

If the `type` of the `destination` option is set to `deeplink`, clicking the banner button will open the app.

| **Option**                  | **Required or Optional** | **Type**     | **Description**                                                      |
| --------------------------- | ------------------------ | ------------ | -------------------------------------------------------------------- |
| `destination.type`          | Required                 | `'deeplink'` | Cannot be changed from<br />`deeplink`                               |
| `destination.deeplinks`     | Optional                 | `object`     | Deep link setting. For more details, refer to this article.          |
| `destination.fallbacks`     | Optional                 | `object`     | Deep link fallback setting. For more details, refer to this article. |
| `destination.defaultParams` | Optional                 | `object`     | Campagin parameter                                                   |
| `destination.ctaParams`     | Optional                 | `object`     | CTA camapgin parameter                                               |

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openBanner({
    title: '<BANNER_TITLE>',
    description: '<BANNER_DESCRIPTION>',
    buttonText: '<BANNER_BUTTON_TEXT>',
    color: '<BANNER_BUTTON_COLOR>',
    position: '<BANNER_POSITION>', // 'top' or 'bottom'
    destination: {
        type: 'deeplink',
        deeplinks: {
            android: '<YOUR_SCHEME>://...',
            ios: '<YOUR_SCHEME>://...',
            desktop: 'https://www.example.com/'
        },
        fallbacks: {
            android: 'google-play',
            ios: 'itunes-appstore',
        },
        ctaParams: {
            cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
            cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
            cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
        },
        defaultParams: {
            campaign: '<EXAMPLE_CAMPAIGN>',
            medium: '<EXAMPLE_MEDIUM>',
            term: '<EXAMPLE_TERM>',
            content: '<EXAMPLE_CONTENT>',
        },
    },
})
```

#### Web-to-Store setup

If the `type` of the `destination` option is set to `download`, clicking the banner button will open the app store.

| **Option**                  | **Required or Optional** | **Type**     | **Description**                        |
| --------------------------- | ------------------------ | ------------ | -------------------------------------- |
| `destination.type`          | Required                 | `'download'` | Cannot be changed from<br />`download` |
| `destination.defaultParams` | Optional                 | `object`     | Campaign parameter                     |
| `destination.ctaParams`     | Optional                 | `object`     | CTA campaign parameter                 |

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openBanner({
    title: '<BANNER_TITLE>',
    description: '<BANNER_DESCRIPTION>',
    buttonText: '<BANNER_BUTTON_TEXT>',
    color: '<BANNER_BUTTON_COLOR>',
    position: '<BANNER_POSITION>', // 'top' or 'bottom'
    destination: {
        type: 'download',
        ctaParams: {
            cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
            cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
            cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
        },
        defaultParams: {
            campaign: '<EXAMPLE_CAMPAIGN>',
            medium: '<EXAMPLE_MEDIUM>',
            term: '<EXAMPLE_TERM>',
            content: '<EXAMPLE_CONTENT>',
        },
    },
})
```

##### Web-to-Web setup

If the `type` of the `destination` option is set to `web`, clicking the banner button will navigate the user to a specified website.

| **Option**         | **Required or Optional** | **Type** | **Description**                    |
| ------------------ | ------------------------ | -------- | ---------------------------------- |
| `destination.type` | Required                 | `'web'`  | Cannot be changed from<br />`web`  |
| `destination.url`  | Required                 | `string` | Input the URL to redirect the user |

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openBanner({
    title: '<BANNER_TITLE>',
    description: '<BANNER_DESCRIPTION>',
    buttonText: '<BANNER_BUTTON_TEXT>',
    color: '<BANNER_BUTTON_COLOR>',
    position: '<BANNER_POSITION>', // 'top' or 'bottom'
    destination: {
        type: 'web',
        url: 'https://www.example.com',
    },
})
```

#### Custom style setup

You can customize the banner's appearance by adding a `styles` field to the options.

Each key should be specified using a CSS selector format, and each value should follow the [`CSSStyleDeclaration`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) ([TypeScript](https://github.com/microsoft/TypeScript/blob/v5.6.3/src/lib/dom.generated.d.ts#L3866-L5111)) format.

See the example below, which changes the `border-radius` of the icon area.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openBanner({
    ...
    styles: {
        '#airbridge-banner-icon': {
            borderRadius: '4px'
        }
    }
})
```

Below is a list of IDs that can be used to apply CSS styles. You can specify the CSS style using a CSS selector format (e.g., `#airbridge-banner-icon`).

| **ID**                         | **Description**        |
| ------------------------------ | ---------------------- |
| `airbridge-banner`             | Entire banner area     |
| `airbridge-banner-icon`        | Banner icon            |
| `airbridge-banner-title`       | Banner title           |
| `airbridge-banner-description` | Banner description     |
| `airbridge-banner-open`        | App dowload cTA button |
| `airbridge-banner-close`       | Banner close button    |

### Implement a custom banner

The Airbridge Web SDK offers features to support custom banner implementation. If you want to add deep linking to an existing banner or build a more advanced custom banner, refer to the following information.

#### Web-to-App setup

You can use the `openDeeplink` function to open the app via a deep link.

| **Option**          | **Required or Optional** | **Type**                      | **Description**                                                                                                                                                                                                                                                              |
| ------------------- | ------------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `deeplinks.android` | Required                 | `string`                      | The scheme URL of the app to be launched via deep link on Android.                                                                                                                                                                                                           |
| `deeplinks.ios`     | Required                 | `string`                      | The scheme URL of the app to be launched via deep link on iOS.                                                                                                                                                                                                               |
| `deeplinks.desktop` | Required                 | `string`                      | The URL of the website to redirect users to on desktop.                                                                                                                                                                                                                      |
| `fallbacks.android` | Required                 | `'google-play' \| string`     | The URL to redirect users to when the deep link fails on an Android device where the app is not installed.<br />- `google-play`: Redirects to the app's Google Play Store page as registered in the Airbridge dashboard.<br />- URL: Redirects to the specified website URL. |
| `fallbacks.ios`     | Required                 | `'itunes-appstore' \| string` | The URL to redirect users to when the deep link fails on an iOS device where the app is not installed.<br />- `itune-appstore`: Redirects to the app's App Store page as registered in the Airbridge dashboard.<br />- URL: Redirects to the specified website URL.          |
| `type`              | Required                 | `'redirect' \| 'click'`       | Select one of the following options depending on the user's interaction.<br />**-** `redirect`: Use when there is no user interaction.<br />- `click`: Use when user interaction is guaranteed (e.g., button click).                                                         |
| `defaultParams`     | Optional                 | `object`                      | Campaign parameter                                                                                                                                                                                                                                                           |
| `ctaParams`         | Optional                 | `object`                      | CTA campaign parameter                                                                                                                                                                                                                                                       |

Refer to the example below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openDeeplink({
    deeplinks: {
        // Please use the custom scheme URL like `<YOUR_SCHEME>://...`
        // Don't use the `intent://...`, `market://...` or `https://...`
        android: '<YOUR_SCHEME>://path?key=value',
        // Please use the custom scheme URL like `<YOUR_SCHEME>://...`
        // Don't use the `intent://...`, `market://...` or `https://...`
        ios: '<YOUR_SCHEME>://path?key=value',
        desktop: 'https://www.example.com/path?key=value',
    },
    fallbacks: {
        // Please use `google-play` or website URL like `https://www.example.com/...`.
        // Don't use the store URL like `https://play.google.com/...`
        android: 'google-play',
        // Please use `itunes-appstore` or website URL like `https://www.example.com/...`.
        // Don't use the store URL like `https://apps.apple.com/...`
        ios: 'itunes-appstore',
    },
    ctaParams: {
        cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
        cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
        cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
    },
})
```

<Danger>
  **Attention**

  Make sure to use **the deep link scheme URLs** configured in the Airbridge dashboard for both `deeplinks.android` and `deeplinks.ios`.

  * `<YOUR_SCHEME>://...`

  Never use the following types of URLs: **Intent scheme URLs** or **HTTP/HTTPS URLs**.

  * `intent://...`
  * `market://...`
  * `https://www.example.com`
</Danger>

Refer to the examples for tracking button-clicking events.

<CodeGroup>
  ```html ES6+ lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">앱으로 보기</button>
  <script>
      document.querySelector('#<BUTTON_ID>').addEventListener('click', () => {
          airbridge.openDeeplink({ ... })
      })
  </script>
  ```

  ```html ES5 lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">앱으로 보기</button>
  <script>
      document.getElementById('<BUTTON_ID>').onclick = function () {
          airbridge.openDeeplink({ ... })
      }
  </script>
  ```
</CodeGroup>

<Danger>
  **Attention**

  Make sure to replace `<BUTTON_ID>` in the example with the actual ID of the button that should trigger the deep link when the user clicks it.
</Danger>

#### Web-to-Store setup

If you don’t input the `deeplinks` option in the `openDeeplink` function and set the `fallbacks` option to `store`, the app store will open regardless of whether the app is installed.

| **Option**          | **Required or Optional** | **Type**            | **Description**                                                                                                                                                                                                |
| ------------------- | ------------------------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fallbacks.android` | Required                 | `'google-play'`     | The destination to redirect users to on an Android device. Cannot be changed from `google-play`.<br />- `google-play`: Redirects to the app's Google Play Store page as registered in the Airbridge dashboard. |
| `fallbacks.ios`     | Required                 | `'itunes-appstore'` | The destination to redirect users to on an iOS device. Cannot be changed from `itune-appstore`.<br />- `itune-appstore`: Redirects to the app's App Store page as registered in the Airbridge dashboard.       |
| `defaultParams`     | Optional                 | `object`            | Campaign parameter                                                                                                                                                                                             |
| `ctaParams`         | Optional                 | `object`            | CTA campaign parameter                                                                                                                                                                                         |

Refer to the example below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openDeeplink({
    fallbacks: {
        android: 'google-play',
        ios: 'itunes-appstore',
    },
    defaultParams: {
        campaign: '<EXAMPLE_CAMPAIGN>',
        medium: '<EXAMPLE_MEDIUM>',
        term: '<EXAMPLE_TERM>',
        content: '<EXAMPLE_CONTENT>',
    },
    ctaParams: {
        cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
        cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
        cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
    },
})
```

Refer to the examples for configuring buttons.

<CodeGroup>
  ```html ES6+ lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">앱 다운로드하기</button>
  <script>
      document.querySelector('#<BUTTON_ID>').addEventListener('click', () => {
          airbridge.openDeeplink({ ... })
      })
  </script>
  ```

  ```html ES5 lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">앱 다운로드하기</button>
  <script>
      document.getElementById('<BUTTON_ID>').onclick = function () {
          airbridge.openDeeplink({ ... })
      }
  </script>
  ```
</CodeGroup>

<Danger>
  **Attention**

  Make sure to replace `<BUTTON_ID>` in the example with the actual ID of the button that should trigger the deep link when the user clicks it.
</Danger>

#### Web-to-Web setup

If you don’t input the `deeplinks` option in the `openDeeplink` function and set the `fallbacks` option to URL, the user will be redirected to the website regardless of whether the app is installed.

| **Option**          | **Required or Optional** | **Type** | **Description**                                                                                            |
| ------------------- | ------------------------ | -------- | ---------------------------------------------------------------------------------------------------------- |
| `fallbacks.android` | Required                 | `string` | The URL to redirect users to on an Android device.<br />- URL: Redirects to the specified website URL.     |
| `fallbacks.ios`     | Required                 | `string` | The destination to redirect users to on an iOS device.<br />- URL: Redirects to the specified website URL. |
| `defaultParams`     | Optional                 | `object` | Campaign parameter                                                                                         |
| `ctaParams`         | Optional                 | `object` | CTA campaign parameter                                                                                     |

Refer to the example below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.openDeeplink({
    fallbacks: {
        android: 'https://www.example.com',
        ios: 'https://www.example.com',
    },
    defaultParams: {
        campaign: '<EXAMPLE_CAMPAIGN>',
        medium: '<EXAMPLE_MEDIUM>',
        term: '<EXAMPLE_TERM>',
        content: '<EXAMPLE_CONTENT>',
    },
    ctaParams: {
        cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
        cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
        cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
    },
})
```

Refer to the examples for configuring buttons.

<CodeGroup>
  ```html ES6+ lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">웹으로 이동하기</button>
  <script>
      document.querySelector('#<BUTTON_ID>').addEventListener('click', () => {
          airbridge.openDeeplink({ ... })
      })
  </script>
  ```

  ```html ES5 lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">웹으로 이동하기</button>
  <script>
      document.getElementById('<BUTTON_ID>').onclick = function () {
          airbridge.openDeeplink({ ... })
      }
  </script>
  ```
</CodeGroup>

<Danger>
  **Attention**

  Make sure to replace `<BUTTON_ID>` in the example with the actual ID of the button that should trigger the deep link when the user clicks it.
</Danger>

### Creating a button to open the app via deep link

<Info>
  **Note**

  The `openDeeplink` function is a unified replacement for the existing `setDeeplinks`, `setDownloads`, and `sendWeb` functions. It is a pure function that can be used independently, without needing to bind it to a DOM element, such as a button.

  The `setDeeplinks` function will be maintained but no longer updated in future releases. Therefore, use the `openDeeplink` function to implement the features you need.
</Info>

You can use the `setDeeplinks` function to assign deep link functionality to a button.

| **Option**          | **Required or Optional** | **Type**                      | **Description**                                                                                                                                                                                                                                                              |
| ------------------- | ------------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `buttonID`          | Required                 | `string \| string[]`          | The `id` attribute of the `<button>` tag to which you want to apply deep link functionality.<br />You can pass multiple values as an array.                                                                                                                                  |
| `deeplinks.android` | Required                 | `string`                      | The scheme URL of the app to be launched via deep link on Android.                                                                                                                                                                                                           |
| `deeplinks.ios`     | Required                 | `string`                      | The scheme URL of the app to be launched via deep link on iOS.                                                                                                                                                                                                               |
| `deeplinks.desktop` | Required                 | `string`                      | The URL of the website to redirect to on desktop.                                                                                                                                                                                                                            |
| `fallbacks.android` | Required                 | `'google-play' \| string`     | The URL to redirect users to when the deep link fails on an Android device where the app is not installed.<br />- `google-play`: Redirects to the app's Google Play Store page as registered in the Airbridge dashboard.<br />- URL: Redirects to the specified website URL. |
| `fallbacks.ios`     | Required                 | `'itunes-appstore' \| string` | The URL to redirect users to when the deep link fails on an iOS device where the app is not installed.<br />- `itune-appstore`: Redirects to the app's App Store page as registered in the Airbridge dashboard.<br />- URL: Redirects to the specified website URL.          |
| `desktopPopUp`      | Optional                 | `boolean`                     | On desktop, the redirection will open in a new window.                                                                                                                                                                                                                       |
| `redirect`          | Optional                 | `boolean`                     | Select one of the following options depending on the user's interaction.<br />**-** `true`: Use when there is no user interaction.<br />- `false`: Use when user interaction is guaranteed (e.g., button click).                                                             |
| `defaultParams`     | Optional                 | `object`                      | Campaign parameter                                                                                                                                                                                                                                                           |
| `ctaParams`         | Optional                 | `object`                      | CTA campaign parameter                                                                                                                                                                                                                                                       |

Refer to the example below.

```html lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
<button id="<BUTTON_ID>">앱으로 보기</button>
<script>
    airbridge.setDeeplinks({
        buttonID: '<BUTTON_ID>', // or ['<BUTTON_ID_1>', '<BUTTON_ID_2>', ...]
        deeplinks: {
            android: '<YOUR_SCHEME>://path?key=value',
            ios: '<YOUR_SCHEME>://path?key=value',
            desktop: 'https://www.example.com/path?key=value',
        },
        fallbacks: {
            android: 'google-play',
            ios: 'itunes-appstore',
        },
        defaultParams: {
            campaign: '<EXAMPLE_CAMPAIGN>',
            medium: '<EXAMPLE_MEDIUM>',
            term: '<EXAMPLE_TERM>',
            content: '<EXAMPLE_CONTENT>',
        },
        ctaParams: {
            cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
            cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
            cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
        },
    })
</script>
```

<Danger>
  **Attention**

  When using the `setDeeplinks` function, the Web SDK manages the button behavior internally, so do not set an `onclick` function on the button. Also, do not use the `id` of an `<a>` tag as the target element.
</Danger>

### Create a button to open the store through a deep link

<Note>
  The `openDeeplink` function is a unified replacement for the existing `setDeeplinks`, `setDownloads`, and `sendWeb` functions. It is a pure function that can be used independently, without needing to bind it to a DOM element, such as a button.

  The `setDownloads` function will be maintained but no longer updated in future releases. Therefore, use the `openDeeplink` function to implement the features you need.
</Note>

You can use the `setDownloads` function to configure the store redirection functionality to a button.

| **Option**      | **Required or Optional** | **Type**             | **Description**                                                                                                                             |
| --------------- | ------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `buttonID`      | Required                 | `string \| string[]` | The `id` attribute of the `<button>` tag to which you want to apply deep link functionality.<br />You can pass multiple values as an array. |
| `defaultParams` | Optional                 | `object`             | Campaign parameter                                                                                                                          |
| `ctaParams`     | Optional                 | `object`             | CTA campaign parameter                                                                                                                      |

```html JavaScript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
<button id="<BUTTON_ID>">앱 다운로드하기</button>
<script>
    airbridge.setDownloads({
        buttonID: '<BUTTON_ID>', // or ['<BUTTON_ID_1>', '<BUTTON_ID_2>', ...]
        defaultParams: {
            campaign: '<EXAMPLE_CAMPAIGN>',
            medium: '<EXAMPLE_MEDIUM>',
            term: '<EXAMPLE_TERM>',
            content: '<EXAMPLE_CONTENT>',
        },
        ctaParams: {
            cta_param_1: '<EXAMPLE_CTA_PARAM_1>',
            cta_param_2: '<EXAMPLE_CTA_PARAM_2>',
            cta_param_3: '<EXAMPLE_CTA_PARAM_3>',
        },
    })
</script>
```

<Danger>
  **Attention**

  When using the `setDownloads` function, the Web SDK manages the button behavior internally, so do not set an `onclick` function on the button. Also, do not use the `id` of an `<a>` tag as the target element.
</Danger>

### Pass attribution data to another website before redirecting

<Note>
  **Attention**

  The `openDeeplink` function is a unified replacement for the existing `setDeeplinks`, `setDownloads`, and `sendWeb` functions. It is a pure function that can be used independently, without needing to bind it to a DOM element, such as a button.

  The `sendWeb` function will be maintained but no longer updated in future releases. Therefore, use the `openDeeplink` function to implement the features you need.
</Note>

You can use the `sendWeb` function to send users to a website on a different domain. In this case, attribution data can be passed across the websites.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.sendWeb('https://other.example.com')
```

If you input a callback function, users are not sent to the website immediately. The URL sent through the callback function can be used freely.

<CodeGroup>
  ```html ES6+ lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">웹으로 이동하기</button>
  <script>
      document.querySelector('#<BUTTON_ID>').addEventListener('click', () => {
          airbridge.sendWeb('https://other.example.com', (error, { targetUrl }) => {
              // Open the link with new window or tab.
              window.open(targetUrl)
          })
      })
  </script>
  ```

  ```html ES5 lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  <button id="<BUTTON_ID>">웹으로 이동하기</button>
  <script>
      document.getElementById('<BUTTON_ID>').onclick = function () {
          airbridge.sendWeb('https://other.example.com', function (error, response) {
              // Open the link with new window or tab.
              window.open(response.targetUrl)
          })
      }
  </script>
  ```
</CodeGroup>

## Additional settings

### Compliance with Google DMA

To comply with the Digital Markets Act (DMA), the user consent data must be sent to Airbridge. For more information about the DMA and whether it applies to your service, refer to the [Airbridge user guide](/en/guides/supporting-the-updated-google-eu-user-consent-policy).

<Danger>
  **Attention**

  Advertisers must collect user consent data from all existing and new users in the EEA at least once starting March 6, 2024.
</Danger>

Refer to the following method.

<Accordion title="Collecting user consent data using the airbridge.setDeviceAlias function">
  <Info>
    **Note**

    Airbridge cannot provide guidance on storing the user consent data and implementing the prompts. For assistance, consult legal professionals.
  </Info>

  1. Check the location of the users who launched the app. If their location is within the EEA, check whether the user consent data has been previously collected. If not, user consent data collection is not required.

  ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  airbridge.init({
      app: 'YOUR_APP_NAME',
      webToken: 'YOUR_WEB_TOKEN',
      // ...
      autoStartTrackingEnabled: false,
  })
  ```

  2. If no user consent data has been collected previously, you may collect the data using a prompt or other means. The user consent data fields that need to be collected are `adPersonalization`, `adUserData.`

  After initializing the Airbridge SDK, send the user consent data and the user location data (`eea`) to the Airbridge SDK using the `airbridge.setDeviceAlias` function.

  ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  // Based on actual region
  airbridge.setDeviceAlias('eea', '0' or '1')

  // Based on actual user consent
  airbridge.setDeviceAlias('adPersonalization', '0' or '1')
  airbridge.setDeviceAlias('adUserData', '0' or '1')
  ```

  Refer to the table below for the user consent data and the user location data that need to be sent to the Airbridge SDK. Note that the Airbridge field names listed in the table below must be used to successfully send data.

  | <span style={{ display: 'inline-block', minWidth: '80px' }}>Airbridge Field Name</span> | <span style={{ display: 'inline-block', minWidth: '80px' }}>Type</span> | <span style={{ display: 'inline-block', minWidth: '80px' }}>Google Field Name</span> | <span style={{ display: 'inline-block', minWidth: '160px' }}>Description</span>                                                                          |
  | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `eea`                                                                                   | `string`                                                                | `eea`                                                                                | Data indicating whether the user location is within the EEA or not<br />- `0`: Non-EEA. DMA not applicable.<br />- `1`: EEA. DMA applicable.             |
  | `adPersonalization`                                                                     | `string`                                                                | `ad_personalization`                                                                 | Data indicating whether the user allowed data tracking for ad personalization<br />- `0`: User didn't allow tracking.<br />- `1`: User allowed tracking. |
  | `adUserData`                                                                            | `string`                                                                | `ad_user_data`                                                                       | Data indicating whether the user allowed data sharing with Google<br />- `0`: User didn't allow sharing.<br />- `1`: User allowed sharing.               |

  3. After the user consent data and the user location data are sent to the Airbridge SDK, call the `startTracking` function.

  ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  airbridge.startTracking()
  ```
</Accordion>

### Pass user data during initialization

You can pass user data during initialization so that all subsequent events include the user data.

The user data you set is stored in the browser’s local storage and will be included in all events **until it is cleared**.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    user: {
        externalUserID: 'personID',
        externalUserEmail: 'persondoe@airbridge.io',
        externalUserPhone: '1(123)123-1234',
        attributes: {
            age_group: 30,
            gender: 'Female'
        },
        alias: {
            custom_id: '83587901-2726-4E29-ACEB-A90B0F7E75F6',
        },
    },
})
```

| **Option**               | **Type**       | **Description**                        |
| ------------------------ | -------------- | -------------------------------------- |
| `user.externalUserID`    | `string`       | User ID                                |
| `user.externalUserEmail` | `string`       | User email                             |
| `user.externalUserPhone` | `string`       | User’s phone number                    |
| `user.attributes`        | `object`       | User attribute (Custom Key Value Pair) |
| `user.alias`             | Obj`object`ect | User identifier                        |

### Set up campaign parameters

When users land on your website through an ad, you can append parameters to the URL to enable web traffic attribution based on that information.

<AccordionGroup>
  <Accordion title="Automatic UTM parameter setting">
    When the `utmParsing` option is set to `true`, UTM-related parameters included in the URL are automatically extracted and attached to events. The default event is `false`.

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.init({
        app: 'YOUR_APP_NAME',
        webToken: 'YOUR_WEB_TOKEN',
        // ...
        utmParsing: true,
    })
    ```

    <Danger>
      **Attention**

      The URL must contain the `utm_source` parameter. Even if the `utmParsing` option is set to `true`, other UTM parameters are ignored when the `utm_source` parameter is not in the URL.
    </Danger>
  </Accordion>

  <Accordion title="Replace the UTM parameter value">
    The `utmParameterValueReplaceMap` option allows you to replace the values of UTM parameters collected through the `utmParsing` option. Supported parameters include `utm_source`, `utm_campaign`, `utm_medium`, `utm_term`, and `utm_content`.

    By using `utmParameterValueReplaceMap`, you can align UTM parameter values collected from various sources, making it easier to analyze data consistently in a single dashboard.

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.init({
        app: '<YOUR_APP_NAME>',
        webToken: '<YOUR_WEB_TOKEN>',
        // ...
        utmParsing: true,
        utmParameterValueReplaceMap: {
            utm_source: {
                'before_replace': 'after_replace',
            },
        },
    })
    ```

    In the example above, if the `utm_source` in the URL is `before_replace` (e.g., `https://www.example.com/?utm_source=before_replace`), the value will be replaced with `after_replace` and sent with the event.
  </Accordion>

  <Accordion title="Set non-UTM parameters as campaign parameters">
    By configuring the `urlQueryMapping` option, you can include non-UTM parameters as campaign parameters and send them with events.

    | **Option**       | **Required or Optional** | **Description**    |
    | ---------------- | ------------------------ | ------------------ |
    | `channel`        | Required                 | Channel            |
    | `campaign`       | Optional                 | Camaign            |
    | `ad_group`       | Optional                 | Ad group           |
    | `ad_creative`    | Optional                 | Ad creative        |
    | `content`        | Optional                 | Content            |
    | `term`           | Optional                 | Search keyword     |
    | `sub_id`         | Optional                 | Sub-publisher      |
    | `sub_id_1`       | Optional                 | Sub-sub publisher1 |
    | `sub_id_2`       | Optional                 | Sub-sub publisher2 |
    | `sub_id_3`       | Optional                 | Sub-sub publisher3 |
    | `campaign_id`    | Optional                 | Campaign ID        |
    | `ad_group_id`    | Optional                 | Ag group ID        |
    | `ad_creative_id` | Optional                 | Ad creative ID     |
    | `term_id`        | Optional                 | Keyword ID         |

    Let’s say, the following URL contains the `utm_source`, `utm_campaign` parameters and the `my_sub_id` parameter that is used within your service.

    * `https://www.example.com/path?utm_source=my_channel&utm_campaign=my_campaign&my_sub_id=example`

    In this case, you can view `sub_id_1` as `my_sub_id` in the Airbridge dashboard, along with `utm_source` and `utm_parameter`.

    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.init({
        app: '<YOUR_APP_NAME>',
        webToken: '<YOUR_WEB_TOKEN>',
        // ...
        urlQueryMapping: {
            channel: 'utm_source',
            campaign: 'utm_campaign',
            sub_id_1: 'my_sub_id',
        },
    })
    ```

    <Danger>
      **Attention**

      Input `channel` in the `urlQueryMapping` option. If not, all other options are also ignored.
    </Danger>
  </Accordion>

  <Accordion title="Manually parse parameters">
    You can manually parse the parameters and pass the information when calling the `init` function.

    | **Option**               | **Required or Optional** | **Description** |
    | ------------------------ | ------------------------ | --------------- |
    | `defaultChannel`         | Optional                 | Ad channel name |
    | `defaultParams.campaign` | Optional                 | Campaign name   |
    | `defaultParams.medium`   | Optional                 | Medium name     |
    | `defaultParams.term`     | Optional                 | Search keywor   |
    | `defaultParams.content`  | Optional                 | Ad content      |

    Refer to the following example.

    <CodeGroup>
      ```javascript JavaScript (ES6+) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      const queryStringToJSON = (url = '') => {
          const { searchParams } = new URL(url)
          return Object.fromEntries(searchParams.entries())
      }

      const url = window.location.href
      const params = queryStringToJSON(url)

      // initialize
      airbridge.init({
          app: '<YOUR_APP_NAME>',
          webToken: '<YOUR_WEB_TOKEN>',
          // ...
          defaultChannel: params['utm_source'],
          defaultParams: {
              campaign: params['utm_campaign'],
              medium: params['utm_medium'],
              content: params['utm_content'],
              term: params['utm_term'],
          },
      })
      ```

      ```javascript JavaScript (ES5) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      function queryStringToJSON(url) {
          url = url || ''
          var index = url.indexOf('?')
          if (index < 0) {
              index = url.length - 1
          }
          var pairs = url.slice(index + 1).split('&')
          var object = {}
          pairs.forEach(function (string) {
              if (string.length === 0) {
                  return
              }
              var pair = string.split('=')
              object[pair[0]] = decodeURIComponent(pair[1] || '')
          })
          return object
      }

      var url = window.location.href
      var params = queryStringToJSON(url)

      // initialize
      airbridge.init({
          app: '<YOUR_APP_NAME>',
          webToken: '<YOUR_WEB_TOKEN>',
          // ...
          defaultChannel: params['utm_source'],
          defaultParams: {
              campaign: params['utm_campaign'],
              medium: params['utm_medium'],
              content: params['utm_content'],
              term: params['utm_term'],
          },
      })
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

### Set delay time to ensure event transmission

You can use the `events.wait` function to ensure that all event transmissions are completed before the user navigates away.

If a page is navigated away before the events are fully transmitted, there is a risk of event data loss. For example, when transmitting event data on an intermediate page that quickly redirects, use `events.wait` and minimize the risk of data loss.

| **Option** | **Type**   | **Description**                   |
| ---------- | ---------- | --------------------------------- |
| `timeout`  | `number`   | Maximum delay time (milliseconds) |
| `callback` | `function` | Event sending complete callback   |

<CodeGroup>
  ```javascript ES6+ lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  airbridge.events.send('category')

  airbridge.events.wait(3000, () => {
      location.href = '<TARGET_URL>'
  })
  ```

  ```javascript ES5 lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  airbridge.events.send('category')

  airbridge.events.wait(3000, function () {
      location.href = '<TARGET_URL>'
  })
  ```
</CodeGroup>

### Edit the attribution window

You can set the attribution window in days using the `cookieWindow` option.

The default setting is 3 days.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    cookieWindowInMinutes: <MINUTES>,
})
```

You can also set the attribution window in minutes using the `cookieWindowInMinutes` option. If both `cookieWindow` option and `cookieWindowInMinutes` option are configured, the `cookieWindowInMinutes` option takes precedence.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    cookieWindow: <DAYS>,
})
```

### Set the attribution window for web-to-app attribution

You can configure the Protected Attribution Window (PAW) using the `useProtectedAttributionWindow` option.

The default setting is `true`.

* When `useProtectedAttributionWindow` is set to `true`, PAW is applied. For more details, refer to the [User Guide](/en/guides/attribution-scenario#%EC%96%B4%ED%8A%B8%EB%A6%AC%EB%B7%B0%EC%85%98-%EA%B3%BC%EC%A0%95-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EA%B8%B0%EB%B3%B8-%EC%84%A4%EC%A0%95-%EB%98%90%EB%8A%94-paw%EB%A5%BC-true%EB%A1%9C-%EC%84%A4%EC%A0%95).
* When `useProtectedAttributionWindow` is set to `false`, PAW is not applied. For more details, refer to the [User Guide](/en/guides/attribution-scenario#%EC%96%B4%ED%8A%B8%EB%A6%AC%EB%B7%B0%EC%85%98-%EA%B3%BC%EC%A0%95-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-paw%EB%A5%BC-false%EB%A1%9C-%EC%84%A4%EC%A0%95).

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: 'YOUR_APP_NAME',
    webToken: 'YOUR_WEB_TOKEN',
    // ...
    useProtectedAttributionWindow: true,
})
```

You can set the Protected Attribution Window (PAW) in minutes using the `protectedAttributionWindowInMinutes` option.

The default value is 30 minutes, and it can be set up to a maximum of 3 days (4320 minutes).

This option is only enabled when `useProtectedAttributionWindow` is set to `true`.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    useProtectedAttributionWindow: true,
    protectedAttributionWindowInMinutes: 60,
})
```

### Share attribution data across subdomains

By default, the Airbridge Web SDK stores attribution data in cookies and uses the root domain's cookie storage. This allows attribution data to be shared across subdomains.

If you're using multiple subdomains, you can configure whether to share cookies between them using the `shareCookieSubdomain` option.

When `shareCookieSubdomain` is set to `false`, data will not be shared between subdomains.

The default setting is `true`.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
// initialize 
airbridge.init({ 
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    shareCookieSubdomain: false,
})
```

<Info>
  **Note**

  Configure the setting based on the following scenarios:

  * Set to `true` if you are operating a single service across multiple subdomains.
  * Set to `false` if you are operating different services on each subdomain.
</Info>

<Accordion title="Example scenario">
  Let’s assume the following scenario:

  1. A user clicks a tracking link for Campaign A and lands on `https://www.airbridge.io` .
  2. The user then clicks a link on the site and is redirected to `https://blog.airbridge.io` .

  In this case, the attribution result will differ depending on the `shareCookieSubdomain` setting:

  * `true`
    * `https://www.airbridge.io` → Attributed to Campaign A
    * `https://blog.airbridge.io` → Attributed to Campaign A
  * `false`
    * `https://www.airbridge.io` → Attributed to Campaign A
    * `https://blog.airbridge.io` → Unattributed

  The **unattributed** case assumes that the Web SDK is installed on `https://blog.airbridge.io`, and that no specific campaign parameter options were added to the `init` function.

  Attribution is determined by the internal logic of the Web SDK based on the options set in the `init` function.
</Accordion>

### Separate storage by app

By default, the Airbridge Web SDK is designed to store attribution data for only one app per domain.

When the `useStoragePerApp` option is set to `true`, data storage is separated, allowing multiple apps using subdomains under the same root domain to manage attribution data independently.

The default setting is `false`.

For example, if multiple apps are used on subdomains that share the same root domain, such as **`a.example.com`** and **`b.example.com`** under **`example.com`**, you can separate the storage by enabling the `useStoragePerApp` option as shown below.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
// Subdomain #1: a.example.com
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    useStoragePerApp: true,
})

// Subdomain #2: b.example.com
airbridge.init({
    app: '<YOUR_ANOTHER_APP_NAME>',
    webToken: '<YOUR_ANOTHER_WEB_TOKEN>',
    // ...
    useStoragePerApp: true,
})
```

<Danger>
  **Attention**

  If you change the `useStoragePerApp` option, the first event triggered in each browser immediately after the change may be **unattributed**.
</Danger>

### Create tracking links from the web

You can create a tracking link using the `createTrackingLink` function. A tracking link is a URL created to transmit touchpoint data generated by users to Airbridge.

With tracking links, you can direct users who have viewed or clicked on an ad to a desired destination. In the Airbridge dashboard, you can use the touchpoint data collected from these tracking links to analyze which channels contributed to conversions.

```typescript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
interface Airbridge {
    createTrackingLink(
        channel: string,
        options: Record<string, boolean | number | string>,
        onSuccess: (trackingLink: TrackingLink) => void
    ): void
    createTrackingLink(
        channel: string,
        options: Record<string, boolean | number | string>,
        onSuccess: (trackingLink: TrackingLink) => void,
        onError: (error: Error) => void
    ): void
}
```

| **Option**  | **Required or Optional** | **Type**   | **Description**                                   |
| ----------- | ------------------------ | ---------- | ------------------------------------------------- |
| `channel`   | Required                 | `string`   | Advertising channel to use with the tracking link |
| `options`   | Required                 | `string`   | Option for creating tracking links                |
| `onSuccess` | Required                 | `function` | Success callback                                  |
| `onError`   | Optional                 | `function` | Failure callback                                  |

<Accordion title="Configure tracking link options">
  You can configure `options` using the following parameters.

  | **Parameter**                    | **Type**                           | **Description**                                                                                                                                                                                                                                                                                                                                                                             |
  | -------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `campaign`                       | `string`                           | Campaign name                                                                                                                                                                                                                                                                                                                                                                               |
  | `ad_group`                       | `string`                           | Ad group                                                                                                                                                                                                                                                                                                                                                                                    |
  | `ad_creative`                    | `string`                           | Ad creative                                                                                                                                                                                                                                                                                                                                                                                 |
  | `content`                        | `string`                           | Ad content                                                                                                                                                                                                                                                                                                                                                                                  |
  | `term`                           | `string`                           | Search keyword                                                                                                                                                                                                                                                                                                                                                                              |
  | `sub_id`                         | `string`                           | An ID that represents a sub-network or affiliate media partner                                                                                                                                                                                                                                                                                                                              |
  | `sub_id_1`                       | `string`                           | An additional sub-network ID (sub-sub publisher).<br />It should be used according to the hierarchy of sub-publishers.<br />(`sub_id_1` > `sub_id_2` > `sub_id_3`)                                                                                                                                                                                                                          |
  | `sub_id_2`                       | `string`                           | An additional sub-network ID (sub-sub publisher).<br />It should be used according to the hierarchy of sub-publishers.<br />(`sub_id_1` > `sub_id_2` > `sub_id_3`)                                                                                                                                                                                                                          |
  | `sub_id_3`                       | `string`                           | An additional sub-network ID (sub-sub publisher).<br />It should be used according to the hierarchy of sub-publishers.<br />(`sub_id_1` > `sub_id_2` > `sub_id_3`)                                                                                                                                                                                                                          |
  | `deeplink_url`                   | `string` (Custom Scheme URL)       | Deeplink URL                                                                                                                                                                                                                                                                                                                                                                                |
  | `deeplink_stopover`              | `boolean`                          | Whether to enable the Stopover Airpage for the deep link<br />- `true` : Enable<br />- `false` : Disable                                                                                                                                                                                                                                                                                    |
  | `fallback_ios`                   | `'store' \| string`                | ios fallback for devices without the app                                                                                                                                                                                                                                                                                                                                                    |
  | `fallback_android`               | `'store' \| string`                | Android fallback for devices without the app                                                                                                                                                                                                                                                                                                                                                |
  | `fallback_desktop`               | `string`                           | Desktop fallback for devices without the app                                                                                                                                                                                                                                                                                                                                                |
  | `fallback_ios_store_ppid`        | `string`                           | The `ppid` of a Custom Product Page on the Apple App Store.<br />Use to display a specific custom product page when landing on the App Store.                                                                                                                                                                                                                                               |
  | `fallback_android_store_listing` | `string`                           | The `listing` value of a Custom Store Listing on the Google Play Store.<br />Use to display a specific custom store listing when landing on the Play Store.                                                                                                                                                                                                                                 |
  | `ogtag_title`                    | `string`                           | `og:title` of the tracking link                                                                                                                                                                                                                                                                                                                                                             |
  | `ogtag_description`              | `string`                           | `og:description` of the tracking link                                                                                                                                                                                                                                                                                                                                                       |
  | `ogtag_image_url`                | `string`                           | `og:image` of the tracking link                                                                                                                                                                                                                                                                                                                                                             |
  | `ogtag_website_crawl`            | `'desktop'`                        | When the tracking link is shared, the social media platform directly crawls the Open Graph of the desktop URL specified in fallbackPaths and uses it for the social share preview. Dynamic URLs are also supported, and any change to the Open Graph is reflected automatically from the next time the link is shared. The values set for title, description, and imageUrl will be ignored. |
  | `custom_short_id`                | `string`                           | Link Short ID for the tracking link when creating a link for a custom channel.<br />Requires a [custom domain](/en/guides/custom-domain) to be set.<br />If not provided, a random ID will be generated. Once the tracking link is created, the short ID cannot be changed.                                                                                                                 |
  | `is_reengagement`                | `'off' \| 'on_true' \| 'on_false'` | Re-engagement parameter<br />`off`: Attributes installs and in-app events to the touchpoint triggered by the tracking link.<br />`on_true`: Attributes only Deep Link Opens and subsequent events. Suitable for re-engagement campaigns.<br />`on_false`: Attributes only installs and in-app events that come after the install. Suitable for UA campaigns.                                |
</Accordion>

Tracking links created using the `createTrackingLink` function are passed via the `onSuccess` callback.

```typescript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
interface TrackingLink {
    shortURL: string
    qrcodeURL: string
}
```

| 이름          | 타입       | 설명                  |
| ----------- | -------- | ------------------- |
| `shortURL`  | `string` | 트래킹 링크의 단축 URL      |
| `qrcodeURL` | `string` | 트래킹 링크의 QR Code URL |

<AccordionGroup>
  <Accordion title="Create tracking links that launch the app or redirect users to the app store">
    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.createTrackingLink(
        'test_channel',
        {
            campaign: 'test_campaign',
            deeplink_url: '<YOUR_SCHEME>://...',
            fallback_ios: 'store',
            fallback_android: 'store',
            fallback_desktop: 'https://www.example.com/'
        },
        ({ shortURL, qrcodeURL }) => {
            // Handling created tracking-link
        },
        (error) => {
            // Handling error
        }
    )
    ```
  </Accordion>

  <Accordion title="Create tracking links that launch the app or redirect users to a webpage">
    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.createTrackingLink(
        'test_channel',
        {
            campaign: 'test_campaign',
            deeplink_url: '<YOUR_SCHEME>://...',
            fallback_ios: 'https://www.example.com/',
            fallback_android: 'https://www.example.com/',
            fallback_desktop: 'https://www.example.com/'
        },
        ({ shortURL, qrcodeURL }) => {
            // Handling created tracking-link
        },
        (error) => {
            // Handling error
        }
    )
    ```
  </Accordion>

  <Accordion title="Create tracking links that redirects users to the app store only">
    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.createTrackingLink(
        'test_channel',
        {
            campaign: 'test_campaign',
            fallback_ios: 'store',
            fallback_android: 'store',
            fallback_desktop: 'https://www.example.com/'
        },
        ({ shortURL, qrcodeURL }) => {
            // Handling created tracking-link
        },
        (error) => {
            // Handling error
        }
    )
    ```
  </Accordion>

  <Accordion title="Create tracking links that redirects users to a webpage only">
    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    airbridge.createTrackingLink(
        'test_channel',
        {
            campaign: 'test_campaign',
            fallback_ios: 'https://www.example.com/',
            fallback_android: 'https://www.example.com/',
            fallback_desktop: 'https://www.example.com/'
        },
        ({ shortURL, qrcodeURL }) => {
            // Handling created tracking-link
        },
        (error) => {
            // Handling error
        }
    )
    ```
  </Accordion>
</AccordionGroup>

### Collect Moloco cookie ID

When `collectMolocoCookieID` is set to `true`, the SDK automatically collects the cookie ID from events driven by Moloco web campaigns, enabling campaign optimization.

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
airbridge.init({
    app: '<YOUR_APP_NAME>',
    webToken: '<YOUR_WEB_TOKEN>',
    // ...
    collectMolocoCookieID: true,
})
```

### Using multiple apps

By defaults, the Airbridge Web SDK is accessed via a global `airbridge` object. However, certain use cases may require the use of independent SDK instances.

The Airbridge Web SDK supports the simultaneous use of multiple Airbridge apps within a single service.

You can create new, isolated instances using the createAirbridge function.

#### Instance creation and initialization

<AccordionGroup>
  <Accordion title="Creation via browser script">
    ```html lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    <script>
    (function(a_,i_,r_,_b,_r,_i,_d,_g,_e){function q(b,a){function d(){var l=x(b,a);y(l)}if(0<_g){var e,f=new (null!=(e=a_.XDomainRequest)?e:a_.XMLHttpRequest);e=function(){};f.open("GET",a);f.timeout=_g;f.onload=d;f.onerror=e;f.onprogress=e;f.ontimeout=e;f.send()}else d()}function y(b){if("complete"===i_.readyState)i_.head.appendChild(b);else{var a=function(){a_.removeEventListener("load",a);i_.head.appendChild(b)};a_.addEventListener("load",a)}}function x(b,a){var d=i_.createElement(r_);d.async=!0;d.src=a;d.onerror=function(){return z(b)};return d}function z(b){b.queue.filter(function(a){return 0<=_d.indexOf(a[0])}).forEach(function(a){a=a[1];a=a[a.length-1];"function"===typeof a&&a("Failed to load Airbridge SDK.")})}function r(b){var a={queue:null!=b?b:[],get isSDKEnabled(){return!1}};_i.concat(_d).forEach(function(d){var e=d.split("."),f=e.pop();e.reduce(function(l,t){var u;return l[t]=null!=(u=l[t])?u:{}},a)[f]=function(){a.queue.push([d,arguments])}});return a}null!=a_.__AIRBRIDGE__||(a_.__AIRBRIDGE__={mocks:[]});"undefined"!==typeof i_.documentMode&&(_r=_r.replace(/^https:/,""));a_.createAirbridge=function(){var b=r(),a;null==(a=a_.__AIRBRIDGE__)||a.mocks.push(b);q(b,_r);return b};a_[_b]||(_e=r(_e),a_[_b]=_e,q(_e,_r))})(window,document,"script","airbridge","https://static.airbridge.io/sdk/latest/airbridge.min.js","init startTracking stopTracking openBanner setBanner setDownload setDownloads openDeeplink setDeeplinks sendWeb setUserAgent setMobileAppData setUserID clearUserID setUserEmail clearUserEmail setUserPhone clearUserPhone setUserAttribute removeUserAttribute clearUserAttributes setUserAlias removeUserAlias clearUserAlias clearUser setUserId setUserAttributes addUserAlias setDeviceAlias removeDeviceAlias clearDeviceAlias setDeviceIFV setDeviceIFA setDeviceGAID events.send events.signIn events.signUp events.signOut events.purchased events.addedToCart events.productDetailsViewEvent events.homeViewEvent events.productListViewEvent events.searchResultViewEvent".split(" "),["events.wait","fetchResource","createTouchpoint","createTrackingLink"],0);

    const customInstance = createAirbridge()
    customInstance.init({
        app: '<YOUR_APP_NAME>',
        webToken: '<YOUR_WEB_TOKEN>',
    })
    </script>
    ```
  </Accordion>

  <Accordion title="Creation via browser script">
    ```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import { createAirbridge } from 'airbridge-web-sdk-loader'

    const customInstance = createAirbridge()
    customInstance.init({
        app: '<YOUR_APP_NAME>',
        webToken: '<YOUR_WEB_TOKEN>',
    })
    ```
  </Accordion>
</AccordionGroup>

Both the global `airbridge` object and any other instances created via `createAirbridge` are fully isolated. This allows all SDK features, including initialization, to be managed and executed separately for each instance.

#### Send web events

```javascript lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
customInstance.events.send('category', {
    label: 'Tool',
    action: 'Hammer',
    value: 10,
    semanticAttributes: {
        currency: 'USD',
        transactionID: 'transaction_123',
        products: [
            {
                productID: 'coke_zero',
                name: 'PlasticHammer',
            },
        ],
    },
    customAttributes: {
        promotion: 'FirstPurchasePromotion',
    },
})
```

<link rel="alternate" hrefLang="en" href="https://help.airbridge.io/en/developers/web-sdk" />

<link rel="alternate" hrefLang="ko" href="https://help.airbridge.io/ko/developers/web-sdk" />
