# Installation and Attribution

### Matching approach

#### **Client-provided data**

The client sends the token (e.g., appsflyer\_id) along with device information. See the request format.

#### Existing installation check

If an installation record with the same token already exists, we return the previously issued installation ID.

#### New installation logic

If no installation with that token is found, we attempt to resolve the installation as follows:

1. **IP-based matching**\
   We compare the request’s **IP address** with user IPs from recent Onside Store sessions (last 24 hours).
2. If we find a match, we generate a new installation ID tied to that specific store user.
3. **Device properties matching**\
   If multiple users share the same IP, we use **device information** to resolve the collision. If we can’t resolve the collision, we generate a completely new installation token.&#x20;
4. If no store sessions match the request IP, we generate a completely new installation token.
5. **Attribution resolution**\
   If the matched store user has attribution data, we include it in the response as `attribution_data`.\
   Otherwise, we return no `attribution data`, indicating an organic user.

An example of matched installation without marketing data (Organic install):

```
# The JWS response
eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpY19rZXlfMSJ9.eyJpc3Mi...
# Decoded response
{
  "iss": "https://onside.io",
  "aud": "com.example.my-awesome-app",
  "iat": 1678886400,
  "exp": 1678890000,
  "jti": "4d3f2c1a-6b7c-4d3f-8c1a-6b7c4d3f8c1a",
  "request_token": "a1b2c3d4-client-random-token-5e6f",
  "installation_token": "a1b2c3d4-onside-install-token-5e6f"
 }
```

An example of matched installation with marketing data (Non-Organic install):

```
# The JWS response
eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpY19rZXlfMSJ9.eyJpc3Mi...
# Decoded response
{
  "iss": "https://onside.io",
  "aud": "com.example.my-awesome-app",
  "iat": 1678886400,
  "exp": 1678890000,
  "jti": "4d3f2c1a-6b7c-4d3f-8c1a-6b7c4d3f8c1a",
  "request_token": "a1b2c3d4-client-random-token-5e6f",
  "installation_token": "a1b2c3d4-onside-install-token-5e6f",
  "attribution_data": {
    "marketing_campaign": "summer_sale_2024",
    "source": "facebook_ads",
    "tags": ["social", "video_ad"],
    "click_id": "clk_123456789"
  }
 }
```

## Get iOS Installation Attribution

> Attempts to match a new app installation with attribution data.

```json
{"openapi":"3.0.1","info":{"title":"Installation Attribution API","version":"1.0.0"},"servers":[{"url":"https://onside.io/","description":"Production Server"},{"url":"https://onside.dev/","description":"Testing Server"}],"paths":{"/merchant-api/v1/attribution/install":{"post":{"summary":"Get iOS Installation Attribution","description":"Attempts to match a new app installation with attribution data.","operationId":"getInstallationAttribution","tags":["Attribution"],"requestBody":{"description":"Device and app information for matching.","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallationRequest"}}}},"responses":{"200":{"description":"**Match Found.**\n\nReturns a signed JSON Web Token (JWT) as a plain text string.\nThe JWT payload contains the installation token and attribution data.\n\n**You must validate the JWT signature** using our public key, \npublished at: `https://onside.io/.well-known/jwks.json`.\n\nCheck `AttributionResponse` for the token schema.\n","content":{"application/jose":{"schema":{"type":"string","format":"jwt"}}}}}}}},"components":{"schemas":{"InstallationRequest":{"type":"object","description":"Information provided by the client device for attribution matching.","required":["token","bundle_id","device_model","os_version","language"],"properties":{"token":{"type":"string","description":"A unique, client-generated random string to bind the installation."},"bundle_id":{"type":"string","description":"The app's bundle identifier."},"device_model":{"type":"string","description":"The device model identifier (e.g., iPhone14,5)."},"os_version":{"type":"string","description":"The version of the device's operating system."},"language":{"type":"string","description":"The device's BCP 47 language code."},"availableCapacity":{"type":"integer","description":"The available disk capacity on the device in bytes"}}}}}}
```

## The InstallationRequest object

```json
{"openapi":"3.0.1","info":{"title":"Installation Attribution API","version":"1.0.0"},"components":{"schemas":{"InstallationRequest":{"type":"object","description":"Information provided by the client device for attribution matching.","required":["token","bundle_id","device_model","os_version","language"],"properties":{"token":{"type":"string","description":"A unique, client-generated random string to bind the installation."},"bundle_id":{"type":"string","description":"The app's bundle identifier."},"device_model":{"type":"string","description":"The device model identifier (e.g., iPhone14,5)."},"os_version":{"type":"string","description":"The version of the device's operating system."},"language":{"type":"string","description":"The device's BCP 47 language code."},"availableCapacity":{"type":"integer","description":"The available disk capacity on the device in bytes"}}}}}}
```

## The AttributionResponse object

```json
{"openapi":"3.0.1","info":{"title":"Installation Attribution API","version":"1.0.0"},"components":{"schemas":{"AttributionResponse":{"type":"object","description":"The decoded payload (claims) of the JWT returned on success.","required":["iss","aud","iat","exp","jti","request_token","installation_token"],"properties":{"iss":{"type":"string","description":"Issuer"},"aud":{"type":"string","description":"Audience (will match the request bundle_id)."},"iat":{"type":"integer","format":"int64","description":"Issued At timestamp (Unix epoch)."},"exp":{"type":"integer","format":"int64","description":"Expiration timestamp (Unix epoch)."},"jti":{"type":"string","description":"JWT ID."},"request_token":{"type":"string","description":"The 'token' you provided in the request, confirming the binding."},"installation_token":{"type":"string","description":"The new, unique installation identifier generated by our system."},"attribution_data":{"$ref":"#/components/schemas/AttributionData"}}},"AttributionData":{"type":"object","description":"Attribution data, if available.","properties":{"marketing_campaign":{"type":"string"},"source":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"click_id":{"type":"string"}}}}}}
```

## The AttributionData object

```json
{"openapi":"3.0.1","info":{"title":"Installation Attribution API","version":"1.0.0"},"components":{"schemas":{"AttributionData":{"type":"object","description":"Attribution data, if available.","properties":{"marketing_campaign":{"type":"string"},"source":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"click_id":{"type":"string"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.onside.io/api/onside-attribution/installation-and-attribution.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
