├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── CONTRIBUTING.md └── workflows │ ├── csharp.yml │ ├── go.yml │ └── kotlin.yml ├── .gitignore ├── LICENSE ├── README.md ├── csharp ├── OpenRTB.Tests │ ├── OpenRTB.Tests.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Tests.cs │ └── packages.config ├── OpenRTB.sln └── OpenRTB │ ├── Enumerations │ ├── Api.cs │ ├── CompanionTypes.cs │ ├── ConnectionType.cs │ ├── CreativeAttributes.cs │ ├── DeliveryMethods.cs │ ├── DeviceType.cs │ ├── Linearity.cs │ ├── LocationType.cs │ ├── PlacementType.cs │ ├── PlaybackMethods.cs │ ├── Position.cs │ └── Protocols.cs │ ├── OpenRTB.csproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── Request │ ├── App.cs │ ├── Banner.cs │ ├── BidRequest.cs │ ├── Data.cs │ ├── Device.cs │ ├── Eid.cs │ ├── Format.cs │ ├── Geo.cs │ ├── Imp.cs │ ├── Publisher.cs │ ├── Regs.cs │ ├── Segment.cs │ ├── Skadn.cs │ ├── Source.cs │ ├── User.cs │ └── Video.cs │ ├── Response │ ├── BidResponse.cs │ ├── ErrResponse.cs │ ├── SkadnResponse.cs │ └── Trackers.cs │ └── packages.config ├── go ├── client │ ├── README.md │ ├── client.go │ ├── client_test.go │ ├── encode.go │ ├── encode_test.go │ ├── validate-request.go │ └── validate-request_test.go ├── decode │ ├── README.md │ ├── request.go │ ├── request_test.go │ ├── response.go │ └── response_test.go ├── examples │ ├── native │ │ └── main.go │ └── proxy-flow │ │ └── main.go ├── go.mod ├── go.sum ├── internal │ └── pool │ │ └── buffer_pool.go ├── native-builder │ └── oneone │ │ ├── builder.go │ │ ├── builder_test.go │ │ └── request │ │ ├── asset.go │ │ ├── data.go │ │ ├── img.go │ │ ├── primitives.go │ │ ├── request.go │ │ ├── request_test.go │ │ └── title.go ├── request │ └── rtb_twofive │ │ ├── README.md │ │ ├── app.go │ │ ├── aps.go │ │ ├── aps_custom_unmarshaller.go │ │ ├── banner.go │ │ ├── bid_request_test.go │ │ ├── data.go │ │ ├── device.go │ │ ├── facebook_test_ad_types.go │ │ ├── format.go │ │ ├── geo.go │ │ ├── identity_link.go │ │ ├── identity_link_test.go │ │ ├── imp.go │ │ ├── mobilefuse_data.go │ │ ├── native.go │ │ ├── primitives.go │ │ ├── primitives_to_references.go │ │ ├── publisher.go │ │ ├── regs.go │ │ ├── request.go │ │ ├── segment.go │ │ ├── skadn.go │ │ ├── source.go │ │ ├── user.go │ │ └── video.go └── response │ ├── README.md │ ├── bid_response.go │ ├── bid_response_test.go │ ├── primitives.go │ ├── skadn.go │ └── trackers.go ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── integration-tests ├── android │ └── build.gradle.kts ├── gradle │ └── libs.versions.toml └── settings.gradle.kts ├── kotlin ├── build.gradle.kts └── src │ ├── androidMain │ └── consumer-proguard-rules.pro │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── adsbynimbus │ │ └── openrtb │ │ ├── enumerations │ │ ├── Apis.kt │ │ ├── CompanionTypes.kt │ │ ├── ConnectionType.kt │ │ ├── CreativeAttributes.kt │ │ ├── DataType.kt │ │ ├── DeliveryMethods.kt │ │ ├── DeviceType.kt │ │ ├── ImageType.kt │ │ ├── Linearity.kt │ │ ├── LocationType.kt │ │ ├── NativeAdContext.kt │ │ ├── NativeAdContextSubType.kt │ │ ├── PlacementType.kt │ │ ├── PlaybackMethods.kt │ │ ├── Position.kt │ │ ├── Protocols.kt │ │ └── TitleLength.kt │ │ ├── request │ │ ├── App.kt │ │ ├── Asset.kt │ │ ├── Banner.kt │ │ ├── BidRequest.kt │ │ ├── Data.kt │ │ ├── Device.kt │ │ ├── Format.kt │ │ ├── Geo.kt │ │ ├── Impression.kt │ │ ├── Native.kt │ │ ├── Publisher.kt │ │ ├── Regs.kt │ │ ├── Segment.kt │ │ ├── Signals.kt │ │ ├── Source.kt │ │ ├── User.kt │ │ └── Video.kt │ │ └── response │ │ └── BidResponse.kt │ └── commonTest │ └── kotlin │ ├── BidRequestTest.kt │ └── BidResponseTest.kt └── settings.gradle.kts /.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | 3 | [*] 4 | charset=utf-8 5 | end_of_line=lf 6 | insert_final_newline=true 7 | indent_style=space 8 | indent_size=4 9 | 10 | [{*.yml,*.yaml}] 11 | indent_size=2 12 | 13 | [*.{kt,kts,gradle}] 14 | ij_kotlin_allow_trailing_comma_on_call_site=true 15 | ij_kotlin_allow_trailing_comma=true -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.kt text 7 | 8 | # Declare files that will always have CRLF line endings on checkout. 9 | *.bat text eol=crlf 10 | *.sh text eol=lf 11 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adsbynimbus/nimbus-openrtb/5136f3be862ddd761daa361dca2cbbaee0642f11/.github/CODEOWNERS -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | ## Adding platforms 4 | 1) Create or checkout a branch named platform/{platform-name} 5 | 2) Commit code and open a Pull Request to main 6 | 3) Squash and merge into main 7 | 4) Delete branch platform/{platform-name} 8 | 9 | ## Working on platform updates 10 | 1) Create a branch named {platform-name}/{feature-name} 11 | 2) Commit code and open a Pull Request to platform/{platform-name} 12 | 3) Squash and merge into platform/{platform-name} 13 | 4) Delete branch {platform-name}/{feature-name} 14 | 15 | This branching methodology allow for simultaneous work contributing to different platform while maintaining high code quality through code reviews -------------------------------------------------------------------------------- /.github/workflows/csharp.yml: -------------------------------------------------------------------------------- 1 | name: CSharp 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths: 7 | - 'csharp/**' 8 | - '.github/workflows/csharp*' 9 | pull_request: 10 | paths: 11 | - 'csharp/**' 12 | - '.github/workflows/csharp*' 13 | 14 | 15 | jobs: 16 | tests: 17 | name: Running CSharp Tests 18 | runs-on: windows-latest 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v4 22 | 23 | - name: Setup dotnet 24 | uses: actions/setup-dotnet@v4 25 | 26 | - uses: actions/cache@v4 27 | with: 28 | path: ~/.nuget/packages 29 | key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.config') }} 30 | restore-keys: | 31 | ${{ runner.os }}-nuget 32 | 33 | - name: Install dependencies 34 | run: nuget restore 35 | working-directory: csharp 36 | 37 | - name: Run Test 38 | run: dotnet test --no-restore 39 | working-directory: csharp 40 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths: 7 | - 'go/**' 8 | - '.github/workflows/go*' 9 | pull_request: 10 | paths: 11 | - 'go/**' 12 | - '.github/workflows/go*' 13 | 14 | 15 | jobs: 16 | test: 17 | name: Running Go Tests 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Set up Go 1.13 21 | uses: actions/setup-go@v5 22 | with: 23 | go-version: 1.13 24 | id: go 25 | 26 | - name: Check out code into the Go module directory 27 | uses: actions/checkout@v4 28 | 29 | - name: Run Test 30 | run: go test ./... -race -cover -v -short 31 | working-directory: go 32 | env: 33 | GOPATH: /home/runner/work/nimbus-openrtb/go 34 | -------------------------------------------------------------------------------- /.github/workflows/kotlin.yml: -------------------------------------------------------------------------------- 1 | name: Kotlin 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '.github/workflows/kotlin*' 7 | - '**/gradle/**' 8 | - 'kotlin/**' 9 | 10 | push: 11 | branches: 12 | - main 13 | paths: 14 | - '.github/workflows/kotlin*' 15 | - '**/gradle/**' 16 | - 'kotlin/**' 17 | 18 | release: 19 | types: [published] 20 | 21 | jobs: 22 | 23 | build: 24 | name: Build Kotlin Multiplatform 25 | runs-on: macos-latest 26 | env: 27 | ORG_GRADLE_PROJECT_githubUsername: ${{ github.actor }} 28 | ORG_GRADLE_PROJECT_githubPassword: ${{ github.token }} 29 | concurrency: 30 | group: ${{ github.workflow }}-${{ github.ref }} 31 | cancel-in-progress: true 32 | permissions: 33 | contents: read 34 | id-token: write 35 | packages: write 36 | steps: 37 | - name: Checkout code 38 | uses: actions/checkout@v4 39 | 40 | - name: Setup Java 41 | uses: actions/setup-java@v4 42 | with: 43 | distribution: 'temurin' 44 | java-version: 17 45 | 46 | - name: Setup Gradle 47 | uses: gradle/actions/setup-gradle@v4 48 | 49 | - name: Cache Kotlin packages 50 | uses: actions/cache@v4 51 | with: 52 | path: ~/.konan 53 | key: ${{ runner.os }}-konan-${{ hashFiles('**/*.versions.toml') }} 54 | restore-keys: | 55 | ${{ runner.os }}-konan-${{ hashFiles('**/*.versions.toml') }} 56 | ${{ runner.os }}-konan- 57 | 58 | - name: Set Version to Tag Name 59 | id: tag_name 60 | if: github.event_name == 'release' 61 | run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_OUTPUT 62 | 63 | - name: Test 64 | env: 65 | ORG_GRADLE_PROJECT_version: ${{ steps.tag_name.outputs.VERSION || 'development' }} 66 | run: ./gradlew test publishToMavenLocal 67 | 68 | - name: Test integration w/ minimum required versions 69 | if: github.event_name != 'release' 70 | run: ./gradlew test -p integration-tests 71 | 72 | - name: Configure AWS Credentials 73 | if: github.repository == 'adsbynimbus/nimbus-openrtb' && github.event_name == 'release' 74 | uses: aws-actions/configure-aws-credentials@v4 75 | with: 76 | role-to-assume: ${{ vars.AWS_ROLE }} 77 | aws-region: us-east-1 78 | 79 | - name: Publish 80 | if: github.repository == 'adsbynimbus/nimbus-openrtb' && github.event_name == 'release' 81 | env: 82 | ORG_GRADLE_PROJECT_version: ${{ steps.tag_name.outputs.VERSION }} 83 | run: ./gradlew publish 84 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Standard 2 | bin/ 3 | build/ 4 | captures/ 5 | classes/ 6 | gen/ 7 | schemas/ 8 | .build/ 9 | .externalNativeBuild/ 10 | .gradle/ 11 | .kotlin/ 12 | .navigation/ 13 | *.aab 14 | *.aar 15 | *.apk 16 | *.framework 17 | *.generated.swift 18 | *.hmap 19 | *.ipa 20 | *.keystore 21 | *.log 22 | *.xcframework 23 | *.zip 24 | 25 | # OS 26 | .DS_Store 27 | 28 | # Intellij / Android Studio / Rider / Fleet 29 | .fleet/ 30 | .idea/ 31 | .vscode/ 32 | *Caches/ 33 | xcuserdata/ 34 | *.iml 35 | *.user 36 | *.xcworkspace 37 | local.properties 38 | 39 | # Nuget 40 | obj/ 41 | packages/ 42 | *.dll 43 | *.nupkg 44 | *.p7s 45 | 46 | # Cocoapods 47 | Pods/ 48 | Podfile.lock 49 | 50 | # Swift Package Manager 51 | .swiftpm/ 52 | Packages/ 53 | Package.resolved 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Nimbus Advertising Solutions Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nimbus OpenRTB 2 | 3 | Platform specific implementations of Nimbus OpenRTB Request and Response models 4 | 5 | ## Platforms 6 | 7 | ### Supported Platforms 8 | 9 | - [![C#](https://github.com/adsbynimbus/nimbus-openrtb/actions/workflows/csharp.yml/badge.svg)](csharp) 10 | - [![Go](https://github.com/adsbynimbus/nimbus-openrtb/actions/workflows/go.yml/badge.svg)](go) 11 | - [![Kotlin](https://github.com/adsbynimbus/nimbus-openrtb/actions/workflows/kotlin.yml/badge.svg)](kotlin) 12 | - [S2S](https://github.com/adsbynimbus/nimbus-openrtb/wiki/Nimbus-S2S-Documentation) 13 | 14 | ### Adding New Platforms 15 | 16 | Refer to [CONTRIBUTING.md](.github/CONTRIBUTING.md) 17 | -------------------------------------------------------------------------------- /csharp/OpenRTB.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OpenRTB.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("OpenRTB.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © 2022")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("175F9A70-807B-469B-8D3A-A65991FE9919")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /csharp/OpenRTB.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /csharp/OpenRTB.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRTB", "OpenRTB\OpenRTB.csproj", "{26758B88-6DCA-4582-A817-2331A6C7940D}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRTB.Tests", "OpenRTB.Tests\OpenRTB.Tests.csproj", "{175F9A70-807B-469B-8D3A-A65991FE9919}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {26758B88-6DCA-4582-A817-2331A6C7940D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {26758B88-6DCA-4582-A817-2331A6C7940D}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {26758B88-6DCA-4582-A817-2331A6C7940D}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {26758B88-6DCA-4582-A817-2331A6C7940D}.Release|Any CPU.Build.0 = Release|Any CPU 17 | {175F9A70-807B-469B-8D3A-A65991FE9919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {175F9A70-807B-469B-8D3A-A65991FE9919}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {175F9A70-807B-469B-8D3A-A65991FE9919}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {175F9A70-807B-469B-8D3A-A65991FE9919}.Release|Any CPU.Build.0 = Release|Any CPU 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/Api.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum Api : byte { 3 | Vpaid = 1, 4 | Vpaid2 = 2, 5 | Mraid1 = 3, 6 | Ormma = 4, 7 | Mraid2 = 5, 8 | Mraid3 = 6, 9 | Omid = 7 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/CompanionTypes.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum CompanionTypes : byte { 3 | Static = 1, 4 | Html = 2, 5 | Iframe = 3 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/ConnectionType.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum ConnectionType : byte { 3 | Unknown = 0, 4 | Ethernet = 1, 5 | Wifi = 2, 6 | CellularUnknown = 3, 7 | Cellular2G = 4, 8 | Cellular3G = 5, 9 | Cellular4G = 6, 10 | Cellular5G = 7 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/CreativeAttributes.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum CreativeAttributes : byte { 3 | AudioAdAutoPlay = 1, 4 | AudioAdUserInitiated = 2, 5 | ExpandableAutomatic = 3, 6 | ExpandableUserClick = 4, 7 | ExpandableUserRollover = 5, 8 | BannerVideoAutoPlay = 6, 9 | BannerVideoUserInitiated = 7, 10 | HasPopup = 8, 11 | ProvocativeOrSuggestive = 9, 12 | ExtremeAnimation = 10, 13 | Surveys = 11, 14 | TextOnly = 12, 15 | UserInteractiveAndGames = 13, 16 | DialogOrAlertStyle = 14, 17 | HasVolumeToggle = 15, 18 | HasSkipButton = 16, 19 | AdobeFlash = 17 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/DeliveryMethods.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum DeliveryMethods : byte { 3 | Streaming = 1, 4 | Progressive = 2, 5 | Download = 3 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/DeviceType.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum DeviceType : byte { 3 | MobileTablet = 1, 4 | PersonalComputer = 2, 5 | ConnectedTv = 3, 6 | Phone = 4, 7 | Tablet = 5, 8 | ConnectedDevice = 6, 9 | SetTopBox = 7 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/Linearity.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum Linearity : byte { 3 | Linear = 1, 4 | NonLinear = 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/LocationType.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum LocationType : byte { 3 | Gps = 1, 4 | IpLookup = 2, 5 | UserProvided = 3 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/PlacementType.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum PlacementType : byte { 3 | InStream = 1, 4 | InBanner = 2, 5 | InArticle = 3, 6 | InFeed = 4, 7 | InterstitialSliderFloating = 5 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/PlaybackMethods.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum PlaybackMethods : byte { 3 | PageLoadSoundOn = 1, 4 | PageLoadSoundOff = 2, 5 | ClickSoundOn = 3, 6 | MouseOverSoundOn = 4, 7 | EnterViewportSoundOn = 5, 8 | EnterViewportSoundOff = 6 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/Position.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum Position : byte { 3 | Unknown = 0, 4 | AboveTheFold = 1, 5 | BelowTheFold = 3, 6 | Header = 4, 7 | Footer = 5, 8 | Sidebar = 6, 9 | Fullscreen = 7 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Enumerations/Protocols.cs: -------------------------------------------------------------------------------- 1 | namespace OpenRTB.Enumerations { 2 | public enum Protocols { 3 | Vast2 = 2, 4 | Vast3 = 3, 5 | Vast2Wrapper = 5, 6 | Vast3Wrapper = 6 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /csharp/OpenRTB/OpenRTB.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {26758B88-6DCA-4582-A817-2331A6C7940D} 8 | Library 9 | Properties 10 | OpenRTB 11 | OpenRTB 12 | v4.6 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OpenRTB")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("OpenRTB")] 12 | [assembly: AssemblyCopyright("Copyright © 2022")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("26758B88-6DCA-4582-A817-2331A6C7940D")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/App.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class App { 5 | [JsonProperty("bundle", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string Bundle; 7 | 8 | [JsonProperty("cat", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string[] Cat; 10 | 11 | [JsonProperty("domain", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Domain; 13 | 14 | [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)] 15 | public string Name; 16 | 17 | [JsonProperty("pagecat", DefaultValueHandling = DefaultValueHandling.Ignore)] 18 | public string[] PageCat; 19 | 20 | [JsonProperty("paid")] public int Paid; 21 | 22 | [JsonProperty("privacypolicy")] public int PrivacyPolicy; 23 | 24 | [JsonProperty("publisher", DefaultValueHandling = DefaultValueHandling.Ignore)] 25 | public Publisher Publisher; 26 | 27 | [JsonProperty("sectioncat", DefaultValueHandling = DefaultValueHandling.Ignore)] 28 | public string[] SectionCat; 29 | 30 | [JsonProperty("storeurl", DefaultValueHandling = DefaultValueHandling.Ignore)] 31 | public string StoreUrl; 32 | 33 | [JsonProperty("ver", DefaultValueHandling = DefaultValueHandling.Ignore)] 34 | public string Ver; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Banner.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using OpenRTB.Enumerations; 3 | 4 | namespace OpenRTB.Request { 5 | public class Banner { 6 | [JsonProperty("api", DefaultValueHandling = DefaultValueHandling.Ignore)] 7 | public Api[] Api; 8 | 9 | [JsonProperty("format", DefaultValueHandling = DefaultValueHandling.Ignore)] 10 | public Format[] Format; 11 | 12 | [JsonProperty("h", Required = Required.Always)] 13 | public int? H; 14 | 15 | [JsonProperty("pos", DefaultValueHandling = DefaultValueHandling.Ignore)] 16 | public Position Pos; 17 | 18 | [JsonProperty("vcm", DefaultValueHandling = DefaultValueHandling.Ignore)] 19 | public int Vcm; 20 | 21 | [JsonProperty("w", Required = Required.Always)] 22 | public int? W; 23 | 24 | [JsonProperty("bidfloor", DefaultValueHandling = DefaultValueHandling.Ignore)] 25 | public float BidFloor; 26 | 27 | [JsonProperty("battr", DefaultValueHandling = DefaultValueHandling.Ignore)] 28 | public CreativeAttributes[] BAttr; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/BidRequest.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class BidRequest { 5 | [JsonProperty("app", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public App App; 7 | 8 | [JsonProperty("badv", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string[] BAdv; 10 | 11 | [JsonProperty("bapp", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string[] BApp; 13 | 14 | [JsonProperty("bcat", DefaultValueHandling = DefaultValueHandling.Ignore)] 15 | public string[] BCat; 16 | 17 | [JsonProperty("wlang", DefaultValueHandling = DefaultValueHandling.Ignore)] 18 | public string[] BLang; 19 | 20 | [JsonProperty("bseat", DefaultValueHandling = DefaultValueHandling.Ignore)] 21 | public string[] BSeat; 22 | 23 | [JsonProperty("device", Required = Required.Always)] 24 | public Device Device; 25 | 26 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 27 | public BidRequestExt Ext; 28 | 29 | [JsonProperty("format", Required = Required.Always)] 30 | public Format Format; 31 | 32 | [JsonProperty("imp", Required = Required.Always)] 33 | public Imp[] Imp; 34 | 35 | [JsonProperty("regs", DefaultValueHandling = DefaultValueHandling.Ignore)] 36 | public Regs Regs; 37 | 38 | [JsonProperty("source", DefaultValueHandling = DefaultValueHandling.Ignore)] 39 | public Source Source; 40 | 41 | [JsonProperty("test")] public int Test; 42 | 43 | [JsonProperty("user", DefaultValueHandling = DefaultValueHandling.Ignore)] 44 | public User User; 45 | 46 | [JsonProperty("wseat", DefaultValueHandling = DefaultValueHandling.Ignore)] 47 | public string[] WSeat; 48 | } 49 | 50 | public class BidRequestExt { 51 | // this is required, however servers are allowed to send this in a header to Nimbus 52 | [JsonProperty("api_key", DefaultValueHandling = DefaultValueHandling.Ignore)] 53 | public string ApiKey; 54 | 55 | [JsonProperty("session_id", Required = Required.Always)] 56 | public string SessionId; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Data.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Data { 5 | [JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string Id; 7 | 8 | [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string Name; 10 | 11 | [JsonProperty("segment", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public Segment[] Segment; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Device.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using OpenRTB.Enumerations; 3 | 4 | namespace OpenRTB.Request { 5 | public class Device { 6 | [JsonProperty("carrier", DefaultValueHandling = DefaultValueHandling.Ignore)] 7 | public string Carrier; 8 | 9 | [JsonProperty("connectiontype")] public ConnectionType ConnectionType; 10 | 11 | [JsonProperty("devicetype", Required = Required.Always)] 12 | public DeviceType? DeviceType; 13 | 14 | [JsonProperty("dnt")] public int Dnt; 15 | 16 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 17 | public DeviceExt Ext; 18 | 19 | [JsonProperty("geo", DefaultValueHandling = DefaultValueHandling.Ignore)] 20 | public Geo Geo; 21 | 22 | [JsonProperty("h", DefaultValueHandling = DefaultValueHandling.Ignore)] 23 | public int H; 24 | 25 | [JsonProperty("hwv", DefaultValueHandling = DefaultValueHandling.Ignore)] 26 | public string Hwv; 27 | 28 | [JsonProperty("ifa", Required = Required.Always)] 29 | public string Ifa; 30 | 31 | [JsonProperty("ip", DefaultValueHandling = DefaultValueHandling.Ignore)] 32 | public string Ip; 33 | 34 | [JsonProperty("language", DefaultValueHandling = DefaultValueHandling.Ignore)] 35 | public string Language; 36 | 37 | [JsonProperty("lmt")] public int Lmt; 38 | 39 | [JsonProperty("make", DefaultValueHandling = DefaultValueHandling.Ignore)] 40 | public string Make; 41 | 42 | [JsonProperty("model", DefaultValueHandling = DefaultValueHandling.Ignore)] 43 | public string Model; 44 | 45 | [JsonProperty("os", Required = Required.Always)] 46 | public string Os; 47 | 48 | [JsonProperty("osv", DefaultValueHandling = DefaultValueHandling.Ignore)] 49 | public string Osv; 50 | 51 | [JsonProperty("ua", Required = Required.Always)] 52 | public string Ua; 53 | 54 | [JsonProperty("w", DefaultValueHandling = DefaultValueHandling.Ignore)] 55 | public int W; 56 | } 57 | 58 | public class DeviceExt { 59 | [JsonProperty("atts", DefaultValueHandling = DefaultValueHandling.Ignore)] 60 | public int Atts; 61 | 62 | [JsonProperty("ifv", DefaultValueHandling = DefaultValueHandling.Ignore)] 63 | public string Ifv; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Eid.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Eid { 5 | [JsonProperty("source", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string Source; 7 | 8 | [JsonProperty("uids", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public Uid[] Uids; 10 | } 11 | 12 | public class Uid { 13 | [JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)] 14 | public string Id; 15 | 16 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 17 | public UidExt UidExt; 18 | } 19 | 20 | public class UidExt { 21 | [JsonProperty("rtiPartner", DefaultValueHandling = DefaultValueHandling.Ignore)] 22 | public string RtiPartner; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Format.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Format { 5 | [JsonProperty("h", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public int H; 7 | 8 | [JsonProperty("w", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public int W; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Geo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Geo { 5 | [JsonProperty("city", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string City; 7 | 8 | [JsonProperty("country", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string Country; 10 | 11 | [JsonProperty("ipservice", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public int IpService; 13 | 14 | [JsonProperty("lat", DefaultValueHandling = DefaultValueHandling.Ignore)] 15 | public float Lat; 16 | 17 | [JsonProperty("lon", DefaultValueHandling = DefaultValueHandling.Ignore)] 18 | public float Lon; 19 | 20 | [JsonProperty("metro", DefaultValueHandling = DefaultValueHandling.Ignore)] 21 | public string Metro; 22 | 23 | [JsonProperty("state", DefaultValueHandling = DefaultValueHandling.Ignore)] 24 | public string State; 25 | 26 | [JsonProperty("type", DefaultValueHandling = DefaultValueHandling.Ignore)] 27 | public int Type; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Imp.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Imp { 5 | [JsonProperty("banner", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public Banner Banner; 7 | 8 | [JsonProperty("ext", Required = Required.Always)] 9 | public ImpExt Ext; 10 | 11 | [JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Id; 13 | 14 | [JsonProperty("instl")] public int Instl; 15 | 16 | [JsonProperty("secure", DefaultValueHandling = DefaultValueHandling.Ignore)] 17 | public int Secure; 18 | 19 | [JsonProperty("video", DefaultValueHandling = DefaultValueHandling.Ignore)] 20 | public Video Video; 21 | } 22 | 23 | public class ImpExt { 24 | [JsonProperty("position", Required = Required.Always)] 25 | public string Position; 26 | 27 | [JsonProperty("skadn", DefaultValueHandling = DefaultValueHandling.Ignore)] 28 | public Skadn Skadn; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Publisher.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Publisher { 5 | [JsonProperty("cat", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string[] Cat; 7 | 8 | [JsonProperty("domain", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string Domain; 10 | 11 | [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Name; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Regs.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Regs { 5 | [JsonProperty("coppa")] public int Coppa; 6 | 7 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 8 | public RegExt Ext; 9 | } 10 | 11 | public class RegExt { 12 | [JsonProperty("gdpr", DefaultValueHandling = DefaultValueHandling.Ignore)] 13 | public int Gdpr; 14 | 15 | [JsonProperty("us_privacy", DefaultValueHandling = DefaultValueHandling.Ignore)] 16 | public string UsPrivacy; 17 | 18 | [JsonProperty("gpp")] 19 | public string GPP; 20 | 21 | [JsonProperty("gpp_sid")] 22 | public string GPPSIDs; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Segment.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Segment { 5 | [JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string Id; 7 | 8 | [JsonProperty("name", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string Name; 10 | 11 | [JsonProperty("value", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Value; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Skadn.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Skadn { 5 | [JsonProperty("skadnetids", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string[] SkadnetIds; 7 | 8 | [JsonProperty("sourceapp", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string SourceApp; 10 | 11 | [JsonProperty("version", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Version; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Source.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class Source { 5 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public SourceExt Ext; 7 | } 8 | 9 | public class SourceExt { 10 | [JsonProperty("omidpn", DefaultValueHandling = DefaultValueHandling.Ignore)] 11 | public string Omidpn; 12 | 13 | [JsonProperty("omidpv", DefaultValueHandling = DefaultValueHandling.Ignore)] 14 | public string Omidpv; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/User.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Request { 4 | public class User { 5 | [JsonProperty("age", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public int Age; 7 | 8 | [JsonProperty("buyeruid", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string BuyerId; 10 | 11 | [JsonProperty("custom_data", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string CustomData; 13 | 14 | [JsonProperty("data", DefaultValueHandling = DefaultValueHandling.Ignore)] 15 | public Data Data; 16 | 17 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 18 | public UserExt Ext; 19 | 20 | [JsonProperty("gender", DefaultValueHandling = DefaultValueHandling.Ignore)] 21 | public string Gender; 22 | 23 | [JsonProperty("keywords", DefaultValueHandling = DefaultValueHandling.Ignore)] 24 | public string Keywords; 25 | 26 | [JsonProperty("yob", DefaultValueHandling = DefaultValueHandling.Ignore)] 27 | public int Yob; 28 | } 29 | 30 | public class UserExt { 31 | [JsonProperty("consent", DefaultValueHandling = DefaultValueHandling.Ignore)] 32 | public string Consent; 33 | 34 | [JsonProperty("eids", DefaultValueHandling = DefaultValueHandling.Ignore)] 35 | public Eid[] Eids; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Request/Video.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using OpenRTB.Enumerations; 3 | 4 | namespace OpenRTB.Request { 5 | public class Video { 6 | [JsonProperty("api", DefaultValueHandling = DefaultValueHandling.Ignore)] 7 | public Api[] Api; 8 | 9 | [JsonProperty("delivery", DefaultValueHandling = DefaultValueHandling.Ignore)] 10 | public DeliveryMethods[] Delivery; 11 | 12 | [JsonProperty("ext", NullValueHandling = NullValueHandling.Ignore)] 13 | public VideoExt Ext; 14 | 15 | [JsonProperty("h", Required = Required.Always)] 16 | public int? H; 17 | 18 | [JsonProperty("linearity", DefaultValueHandling = DefaultValueHandling.Ignore)] 19 | public Linearity Linearity; 20 | 21 | [JsonProperty("maxbitrate", DefaultValueHandling = DefaultValueHandling.Ignore)] 22 | public int MaxBitrate; 23 | 24 | [JsonProperty("maxduration", DefaultValueHandling = DefaultValueHandling.Ignore)] 25 | public int MaxDuration; 26 | 27 | [JsonProperty("mimes", DefaultValueHandling = DefaultValueHandling.Ignore)] 28 | public string[] Mimes; 29 | 30 | [JsonProperty("minbitrate", DefaultValueHandling = DefaultValueHandling.Ignore)] 31 | public int MinBitrate; 32 | 33 | [JsonProperty("minduration", DefaultValueHandling = DefaultValueHandling.Ignore)] 34 | public int MinDuration; 35 | 36 | [JsonProperty("placement", DefaultValueHandling = DefaultValueHandling.Ignore)] 37 | public PlacementType Placement; 38 | 39 | [JsonProperty("playbackmethod", DefaultValueHandling = DefaultValueHandling.Ignore)] 40 | public PlaybackMethods[] PlaybackMethod; 41 | 42 | [JsonProperty("pos")] public Position Pos; 43 | 44 | [JsonProperty("protocols", DefaultValueHandling = DefaultValueHandling.Ignore)] 45 | public Protocols[] Protocols; 46 | 47 | [JsonProperty("skip")] public int Skip; 48 | 49 | [JsonProperty("startdelay")] public int StartDelay; 50 | 51 | [JsonProperty("w", Required = Required.Always)] 52 | public int? W; 53 | 54 | [JsonProperty("bidfloor", DefaultValueHandling = DefaultValueHandling.Ignore)] 55 | public float BidFloor; 56 | 57 | [JsonProperty("companionad", DefaultValueHandling = DefaultValueHandling.Ignore)] 58 | public Banner[] CompanionAd; 59 | 60 | [JsonProperty("companiontype", DefaultValueHandling = DefaultValueHandling.Ignore)] 61 | public CompanionTypes[] CompanionType; 62 | } 63 | 64 | public class VideoExt { 65 | [JsonProperty("is_rewarded")] public int IsRewarded; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Response/BidResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Response { 4 | public struct BidResponse { 5 | [JsonProperty("type")] public string Type; 6 | [JsonProperty("auction_id")] public string AuctionId; 7 | 8 | [JsonProperty("adomain", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string[] Adomain; 10 | 11 | [JsonProperty("bid_in_cents")] public int BidInCents; 12 | [JsonProperty("bid_raw")] public float BidRaw; 13 | [JsonProperty("content_type")] public string ContentType; 14 | 15 | [JsonProperty("crid", DefaultValueHandling = DefaultValueHandling.Ignore)] 16 | public string Crid; 17 | 18 | [JsonProperty("height", DefaultValueHandling = DefaultValueHandling.Ignore)] 19 | public int Height; 20 | 21 | [JsonProperty("width", DefaultValueHandling = DefaultValueHandling.Ignore)] 22 | public int Width; 23 | 24 | [JsonProperty("is_interstitial")] public int IsInterstitial; 25 | [JsonProperty("is_mraid")] public int IsMraid; 26 | [JsonProperty("markup")] public string Markup; 27 | [JsonProperty("network")] public string Network; 28 | [JsonProperty("position")] public string Position; 29 | 30 | [JsonProperty("trackers", DefaultValueHandling = DefaultValueHandling.Ignore)] 31 | public Trackers Trackers; 32 | 33 | [JsonProperty("placement_id", DefaultValueHandling = DefaultValueHandling.Ignore)] 34 | public string PlacementId; 35 | 36 | [JsonProperty("duration", DefaultValueHandling = DefaultValueHandling.Ignore)] 37 | public int Duration; 38 | 39 | [JsonProperty("ext", DefaultValueHandling = DefaultValueHandling.Ignore)] 40 | public BidExt Ext; 41 | } 42 | 43 | public struct BidExt { 44 | [JsonProperty("skadn", DefaultValueHandling = DefaultValueHandling.Ignore)] 45 | public SkadnResponse Skadn; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Response/ErrResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Response { 4 | public struct ErrResponse { 5 | [JsonProperty("id")] public string Id; 6 | [JsonProperty("status_code")] public int StatusCode; 7 | [JsonProperty("nbr")] public int Nrb; 8 | [JsonProperty("message")] public string Message; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Response/SkadnResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Response { 4 | public struct SkadnResponse { 5 | [JsonProperty("version", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string Version; 7 | 8 | [JsonProperty("network", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string Network; 10 | 11 | [JsonProperty("campaign", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Campaign; 13 | 14 | [JsonProperty("itunesitem", DefaultValueHandling = DefaultValueHandling.Ignore)] 15 | public string Itunesitem; 16 | 17 | [JsonProperty("nonce", DefaultValueHandling = DefaultValueHandling.Ignore)] 18 | public string Nonce; 19 | 20 | [JsonProperty("sourceapp", DefaultValueHandling = DefaultValueHandling.Ignore)] 21 | public string Sourceapp; 22 | 23 | [JsonProperty("timestamp", DefaultValueHandling = DefaultValueHandling.Ignore)] 24 | public string Timestamp; 25 | 26 | [JsonProperty("signature", DefaultValueHandling = DefaultValueHandling.Ignore)] 27 | public string Signature; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /csharp/OpenRTB/Response/Trackers.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace OpenRTB.Response { 4 | public struct Trackers { 5 | [JsonProperty("impression_trackers", DefaultValueHandling = DefaultValueHandling.Ignore)] 6 | public string[] ImpressionTrackers; 7 | 8 | [JsonProperty("click_trackers", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string[] ClickTrackers; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /csharp/OpenRTB/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /go/client/encode.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | 7 | "github.com/francoispqt/gojay" 8 | ) 9 | 10 | // MarshalBidRequest calls gojay to marshal data, if that fails we fallback to the standard package 11 | func MarshalBidRequest(v interface{}) ([]byte, error) { 12 | // byte buffers grow more effiently than the encoder gojay is using internally 13 | b := new(bytes.Buffer) 14 | enc := gojay.BorrowEncoder(b) 15 | defer enc.Release() 16 | 17 | // addding fall back logic for normal behavior 18 | err := enc.Encode(v) 19 | if err != nil { 20 | tb, err := json.Marshal(v) 21 | if err != nil { 22 | return nil, err 23 | } 24 | _, _ = b.Write(tb) 25 | } 26 | 27 | return b.Bytes(), nil 28 | } 29 | -------------------------------------------------------------------------------- /go/client/validate-request.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import "github.com/marcsantiago/govalidator" 4 | 5 | // IsRequestValid will validate the structure 6 | // result will be equal to `false` if there are any errors 7 | // the error will contain a small description about the failure 8 | func IsRequestValid(requestStructure interface{}) (bool, error) { 9 | return govalidator.ValidateStruct(requestStructure) 10 | } 11 | -------------------------------------------------------------------------------- /go/client/validate-request_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import "testing" 4 | 5 | func TestIsRequestValid(t *testing.T) { 6 | type foo struct { 7 | Bar string `valid:"in(bar|nimbus),required"` 8 | Ping int `valid:"range(0|10),required"` 9 | Pong float64 `valid:"required"` 10 | } 11 | 12 | type args struct { 13 | requestStructure interface{} 14 | } 15 | tests := []struct { 16 | name string 17 | args args 18 | want bool 19 | wantErr bool 20 | }{ 21 | { 22 | name: "structure should be valid", 23 | args: args{ 24 | requestStructure: foo{ 25 | Bar: "nimbus", 26 | Ping: 10, 27 | Pong: 1.00, 28 | }, 29 | }, 30 | want: true, 31 | wantErr: false, 32 | }, 33 | { 34 | name: "structure should be invalid, bar does not validate", 35 | args: args{ 36 | requestStructure: foo{ 37 | Bar: "foo", 38 | Ping: 10, 39 | Pong: 1.00, 40 | }, 41 | }, 42 | want: false, 43 | wantErr: true, 44 | }, 45 | { 46 | name: "structure should be invalid, ping is to high", 47 | args: args{ 48 | requestStructure: foo{ 49 | Bar: "bar", 50 | Ping: 20, 51 | Pong: 1.00, 52 | }, 53 | }, 54 | want: false, 55 | wantErr: true, 56 | }, 57 | { 58 | name: "structure should be invalid, ping is missing", 59 | args: args{ 60 | requestStructure: foo{ 61 | Bar: "bar", 62 | Ping: 5, 63 | }, 64 | }, 65 | want: false, 66 | wantErr: true, 67 | }, 68 | } 69 | for _, tt := range tests { 70 | t.Run(tt.name, func(t *testing.T) { 71 | got, err := IsRequestValid(tt.args.requestStructure) 72 | if (err != nil) != tt.wantErr { 73 | t.Errorf("IsRequestValid() error = %v, wantErr %v", err, tt.wantErr) 74 | return 75 | } 76 | if got != tt.want { 77 | t.Errorf("IsRequestValid() = %v, want %v", got, tt.want) 78 | } 79 | }) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /go/decode/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # decode 4 | `import "github.com/adsbynimbus/nimbus-openrtb/go/decode"` 5 | 6 | * [Overview](#pkg-overview) 7 | * [Index](#pkg-index) 8 | 9 | ## Overview 10 | 11 | 12 | 13 | ## Index 14 | * [func RequestToStruct(res *http.Request, v interface{}) error](#RequestToStruct) 15 | * [func ResponseToStruct(res *http.Response, v interface{}) error](#ResponseToStruct) 16 | 17 | 18 | #### Package files 19 | [request.go](/src/github.com/adsbynimbus/nimbus-openrtb/go/decode/request.go) [response.go](/src/github.com/adsbynimbus/nimbus-openrtb/go/decode/response.go) 20 | 21 | 22 | 23 | 24 | 25 | ## func [RequestToStruct](/src/target/request.go?s=271:331#L15) 26 | ``` go 27 | func RequestToStruct(res *http.Request, v interface{}) error 28 | ``` 29 | RequestToStruct takes the a request generically, checks the Content-Encoding 30 | and unmarshals the object to the provided data structure 31 | 32 | 33 | 34 | ## func [ResponseToStruct](/src/target/response.go?s=333:395#L20) 35 | ``` go 36 | func ResponseToStruct(res *http.Response, v interface{}) error 37 | ``` 38 | ResponseToStruct takes the response generically, checks the Content-Encoding 39 | and unmarshals the object to the provided data structure 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | - - - 49 | Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) 50 | -------------------------------------------------------------------------------- /go/decode/request.go: -------------------------------------------------------------------------------- 1 | package decode 2 | 3 | import ( 4 | "compress/flate" 5 | "compress/gzip" 6 | "encoding/json" 7 | "io" 8 | "net/http" 9 | 10 | "github.com/francoispqt/gojay" 11 | ) 12 | 13 | // RequestToStruct takes the a request generically, checks the Content-Encoding 14 | // and unmarshals the object to the provided data structure 15 | func RequestToStruct(res *http.Request, v interface{}) error { 16 | var reader io.ReadCloser 17 | var err error 18 | switch res.Header.Get("Content-Encoding") { 19 | case gzipHeader: 20 | reader, err = gzip.NewReader(res.Body) 21 | if err != nil { 22 | return err 23 | } 24 | defer reader.Close() 25 | case deflateHeader: 26 | reader = flate.NewReader(res.Body) 27 | defer reader.Close() 28 | default: 29 | reader = res.Body 30 | } 31 | 32 | decoder := gojay.BorrowDecoder(reader) 33 | defer decoder.Release() 34 | 35 | err = decoder.Decode(&v) 36 | if err != nil { 37 | return json.NewDecoder(reader).Decode(v) 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /go/decode/request_test.go: -------------------------------------------------------------------------------- 1 | package decode 2 | 3 | import ( 4 | "bytes" 5 | "compress/flate" 6 | "compress/gzip" 7 | "encoding/json" 8 | "io/ioutil" 9 | "net/http" 10 | "testing" 11 | 12 | twofive "github.com/adsbynimbus/nimbus-openrtb/go/request/rtb_twofive" 13 | "github.com/google/go-cmp/cmp" 14 | ) 15 | 16 | var jsonRequestTestBody = []byte(`{"imp":[{"banner":{"w":320,"h":480,"pos":7,"api":[3,5]},"instl":1,"bidfloor":2}],"app":{"name":"foo","bundle":"bar","domain":"https://foo.com","storeurl":"https://itunes.apple.com/us/app/foo","cat":["IAB14","IAB1","IAB9"],"privacypolicy":1,"paid":0,"publisher":{"name":"foo","domain":"https://foo.com"}},"device":{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4","geo":{"lat":37.751,"lon":-97.822,"ipservice":3,"country":"USA","city":"New York"},"dnt":0,"lmt":0,"ip":"174.193.148.17","make":"Apple","model":"iPhone","os":"ios","osv":"10.3.2","language":"en","carrier":"Verizon","connection_type":6,"ifa":"13579176-e94e-4e6e-96ae-572b787af21c"},"user":{"gender":"male"},"format":{"h":480,"w":360},"at":1,"regs":{"ext":{"gdpr":1,"us_privacy":"1YNY","gpp":"DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA","gpp_sid":"2"}},"ext":{"api_key":"83499783-c452-461f-8c37-43877f859ba3","session_id":"1","position":"pingpong"}}`) 17 | 18 | func TestRequestToStruct(t *testing.T) { 19 | // gzipped request 20 | var b bytes.Buffer 21 | gzipw := gzip.NewWriter(&b) 22 | gzipw.Write(jsonRequestTestBody) 23 | gzipw.Close() 24 | 25 | header := make(http.Header) 26 | header.Add("Content-Encoding", gzipHeader) 27 | 28 | // flated request, which is gzip without the error handling 29 | var b2 bytes.Buffer 30 | flatew, _ := flate.NewWriter(&b2, flate.BestSpeed) 31 | flatew.Write(jsonRequestTestBody) 32 | flatew.Close() 33 | 34 | header2 := make(http.Header) 35 | header2.Add("Content-Encoding", deflateHeader) 36 | 37 | type args struct { 38 | res *http.Request 39 | } 40 | tests := []struct { 41 | name string 42 | args args 43 | want []byte 44 | wantErr bool 45 | }{ 46 | { 47 | name: "should decode the body when the content-encoding header is set and gzip", 48 | args: args{ 49 | &http.Request{ 50 | Header: header, 51 | Body: ioutil.NopCloser(bytes.NewReader(b.Bytes())), 52 | }, 53 | }, 54 | want: jsonRequestTestBody, 55 | wantErr: false, 56 | }, 57 | { 58 | name: "should decode the body when the content-encoding header is set and flate", 59 | args: args{ 60 | &http.Request{ 61 | Header: header2, 62 | Body: ioutil.NopCloser(bytes.NewReader(b2.Bytes())), 63 | }, 64 | }, 65 | want: jsonRequestTestBody, 66 | wantErr: false, 67 | }, 68 | { 69 | name: "should decode the body when the content-encoding unset", 70 | args: args{ 71 | &http.Request{ 72 | Body: ioutil.NopCloser(bytes.NewReader(jsonRequestTestBody)), 73 | }, 74 | }, 75 | want: jsonRequestTestBody, 76 | wantErr: false, 77 | }, 78 | { 79 | name: "should not decode the body because the header is missing, but the content is gzipped", 80 | args: args{ 81 | &http.Request{ 82 | Body: ioutil.NopCloser(bytes.NewReader(b.Bytes())), 83 | }, 84 | }, 85 | want: b.Bytes(), 86 | wantErr: true, 87 | }, 88 | } 89 | for _, tt := range tests { 90 | t.Run(tt.name, func(t *testing.T) { 91 | var br twofive.Request 92 | err := RequestToStruct(tt.args.res, &br) 93 | if (err != nil) != tt.wantErr { 94 | t.Errorf("RequestToStruct() error = %v, wantErr %v", err, tt.wantErr) 95 | return 96 | } 97 | 98 | if !tt.wantErr { 99 | var wbr twofive.Request 100 | _ = json.Unmarshal(tt.want, &wbr) 101 | if !cmp.Equal(br, wbr) { 102 | t.Errorf("RequestToStruct() got = %v, want %v", br, wbr) 103 | } 104 | } 105 | }) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /go/decode/response.go: -------------------------------------------------------------------------------- 1 | package decode 2 | 3 | import ( 4 | "compress/flate" 5 | "compress/gzip" 6 | "encoding/json" 7 | "io" 8 | "io/ioutil" 9 | "net/http" 10 | 11 | "github.com/francoispqt/gojay" 12 | ) 13 | 14 | const ( 15 | gzipHeader = "gzip" 16 | deflateHeader = "deflate" 17 | ) 18 | 19 | // ResponseToStruct takes the response generically, checks the Content-Encoding 20 | // and unmarshals the object to the provided data structure 21 | func ResponseToStruct(res *http.Response, v interface{}) error { 22 | var reader io.ReadCloser 23 | var err error 24 | switch res.Header.Get("Content-Encoding") { 25 | case gzipHeader: 26 | reader, err = gzip.NewReader(res.Body) 27 | if err != nil { 28 | return err 29 | } 30 | defer reader.Close() 31 | case deflateHeader: 32 | reader = flate.NewReader(res.Body) 33 | defer reader.Close() 34 | default: 35 | reader = res.Body 36 | } 37 | 38 | decoder := gojay.BorrowDecoder(reader) 39 | defer decoder.Release() 40 | 41 | err = decoder.Decode(&v) 42 | if err != nil { 43 | return json.NewDecoder(reader).Decode(v) 44 | } 45 | 46 | return nil 47 | } 48 | 49 | // ResponseToBytes takes the Nimbus response, decodes if neccasary and returns the body as bytes 50 | // if the Content-Encoding header is missing this can silently fail 51 | func ResponseToBytes(res *http.Response) ([]byte, error) { 52 | var reader io.ReadCloser 53 | var err error 54 | switch res.Header.Get("Content-Encoding") { 55 | case gzipHeader: 56 | reader, err = gzip.NewReader(res.Body) 57 | if err != nil { 58 | return nil, err 59 | } 60 | defer reader.Close() 61 | case deflateHeader: 62 | reader = flate.NewReader(res.Body) 63 | defer reader.Close() 64 | default: 65 | reader = res.Body 66 | } 67 | return ioutil.ReadAll(reader) 68 | } 69 | -------------------------------------------------------------------------------- /go/examples/native/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | 8 | "github.com/adsbynimbus/nimbus-openrtb/go/native-builder/oneone" 9 | "github.com/adsbynimbus/nimbus-openrtb/go/native-builder/oneone/request" 10 | twofive "github.com/adsbynimbus/nimbus-openrtb/go/request/rtb_twofive" 11 | ) 12 | 13 | func main() { 14 | bidRequest := twofive.Request{ 15 | App: twofive.App{ 16 | Name: "foo", 17 | Bundle: "com.foo", 18 | Domain: "foo.com", 19 | StoreURL: "https://play.google.com/store/apps/details?id=com.foo", 20 | Cat: []string{"IAB14", "IAB1", "IAB9", "IAB12", "IAB16", "IAB17", "IAB18", "IAB20"}, 21 | Publisher: twofive.Publisher{ 22 | Name: "foo", 23 | Cat: []string{"IAB14", "IAB1", "IAB9", "IAB12", "IAB16", "IAB17", "IAB18", "IAB20"}, 24 | Domain: "foo.com", 25 | }, 26 | }, 27 | Device: twofive.Device{ 28 | DeviceType: 1, 29 | Ua: "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36", 30 | IP: "71.125.59.151", 31 | Make: "Pixel 2 XL", 32 | Model: "Samsung", 33 | OS: "android", 34 | OSV: "4.2.4", 35 | Language: "en", 36 | ConnectionType: 6, 37 | Ifa: "13579176-e94e-4e6e-96ae-572b787af21c", 38 | }, 39 | Format: &twofive.Format{ 40 | H: 1920, 41 | W: 1080, 42 | }, 43 | User: twofive.User{ 44 | Age: 30, 45 | YOB: 1991, 46 | Gender: "male", 47 | }, 48 | Ext: twofive.RequestExt{ 49 | APIKey: "3b117631-538d-4315-bc47-d4e8ce6527e5", 50 | SessionID: "fab5d528-5ac9-4082-a1ff-968a7f8fefc4", 51 | }, 52 | // creative an impression object with the Native object helpers 53 | Imp: []twofive.Imp{ 54 | twofive.Imp{ 55 | Instl: 1, 56 | BidFloor: 1.00, 57 | Secure: twofive.IntPointer(1), 58 | Native: &twofive.Native{ 59 | Request: oneone.BuildDefaultImageNative(300, 250), 60 | Ver: request.Version, 61 | }, 62 | }, 63 | }, 64 | } 65 | 66 | // printing out example of generated body 67 | b, err := json.MarshalIndent(bidRequest, "", " ") 68 | if err != nil { 69 | log.Fatal(err) 70 | } 71 | fmt.Println(string(b)) 72 | } 73 | -------------------------------------------------------------------------------- /go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/adsbynimbus/nimbus-openrtb/go 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/francoispqt/gojay v1.2.13 7 | github.com/google/go-cmp v0.3.1 8 | github.com/marcsantiago/govalidator v0.0.0-20190311185458-b237937e4a00 9 | ) 10 | -------------------------------------------------------------------------------- /go/internal/pool/buffer_pool.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "bytes" 5 | "sync" 6 | ) 7 | 8 | // bytesBuffer creates a Bytes.Buffer pool that can be used to stop object churn 9 | var bytesBuffer = sync.Pool{ 10 | // New is called when a new instance is needed 11 | New: func() interface{} { 12 | return new(bytes.Buffer) 13 | }, 14 | } 15 | 16 | // GetBuffer fetches a buffer from the pool 17 | func GetBuffer() *bytes.Buffer { 18 | return bytesBuffer.Get().(*bytes.Buffer) 19 | } 20 | 21 | // PutBuffer returns a buffer to the pool, never call this with defer in loops 22 | func PutBuffer(buf *bytes.Buffer) { 23 | buf.Reset() 24 | bytesBuffer.Put(buf) 25 | } 26 | -------------------------------------------------------------------------------- /go/native-builder/oneone/builder.go: -------------------------------------------------------------------------------- 1 | package oneone 2 | 3 | import ( 4 | "github.com/adsbynimbus/nimbus-openrtb/go/internal/pool" 5 | "github.com/adsbynimbus/nimbus-openrtb/go/native-builder/oneone/request" 6 | "github.com/francoispqt/gojay" 7 | ) 8 | 9 | // BuildDefaultImageNative creatives a Native RTB Request string 1.1 10 | func BuildDefaultImageNative(wmin, hmin int) string { 11 | // have to allocate this object... in the future we can back this object by a sync pool 12 | r := request.Request{ 13 | Plcmttype: 1, 14 | Plcmtcnt: 1, 15 | Ver: request.Version, 16 | Required: 1, 17 | Assets: []request.Asset{ 18 | request.Asset{ 19 | ID: 1, 20 | Img: request.Img{ 21 | Hmin: hmin, 22 | Wmin: wmin, 23 | Type: 3, 24 | Mimes: []string{ 25 | "image/jpeg", 26 | "image/png", 27 | "image/gif", 28 | }, 29 | }, 30 | Title: request.Title{ 31 | Len: 140, 32 | }, 33 | Data: request.Data{ 34 | Type: 2, 35 | Len: 140, 36 | }, 37 | Required: 1, 38 | }, 39 | }, 40 | } 41 | 42 | b := pool.GetBuffer() 43 | defer pool.PutBuffer(b) 44 | 45 | enc := gojay.BorrowEncoder(b) 46 | defer enc.Release() 47 | 48 | err := enc.Encode(&r) 49 | if err != nil { 50 | return "" 51 | } 52 | 53 | return b.String() 54 | } 55 | -------------------------------------------------------------------------------- /go/native-builder/oneone/builder_test.go: -------------------------------------------------------------------------------- 1 | package oneone 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/google/go-cmp/cmp" 8 | ) 9 | 10 | func TestBuildDefaultImageNative(t *testing.T) { 11 | type args struct { 12 | hmin int 13 | wmin int 14 | } 15 | tests := []struct { 16 | name string 17 | args args 18 | want string 19 | }{ 20 | { 21 | name: "should build a native-builder request just fine", 22 | args: args{ 23 | hmin: 300, 24 | wmin: 250, 25 | }, 26 | want: `{"assets":[{"id":1,"img":{"hmin":250,"type":3,"wmin":300,"mimes":["image/jpeg","image/png","image/gif"]},"title":{"len":140},"data":{"type":2,"len":140},"required":1}],"plcmttype":1,"plcmtcnt":1,"required":1,"ver":"1.1"}`, 27 | }, 28 | } 29 | for _, tt := range tests { 30 | t.Run(tt.name, func(t *testing.T) { 31 | if got := BuildDefaultImageNative(tt.args.hmin, tt.args.wmin); !cmp.Equal(got, tt.want) { 32 | t.Errorf("BuildDefaultImageNative() = %v, want %v", got, tt.want) 33 | } 34 | }) 35 | } 36 | } 37 | 38 | var s string 39 | 40 | // BenchmarkBuildDefaultImageNative-12 2000000 949 ns/op 496 B/op 6 allocs/op 41 | func BenchmarkBuildDefaultImageNative(b *testing.B) { 42 | for i := 0; i < b.N; i++ { 43 | s = BuildDefaultImageNative(300, 250) 44 | } 45 | } 46 | 47 | func deepAllowUnexported(vs ...interface{}) cmp.Option { 48 | m := make(map[reflect.Type]struct{}) 49 | for _, v := range vs { 50 | structTypes(reflect.ValueOf(v), m) 51 | } 52 | var typs []interface{} 53 | for t := range m { 54 | typs = append(typs, reflect.New(t).Elem().Interface()) 55 | } 56 | return cmp.AllowUnexported(typs...) 57 | } 58 | 59 | func structTypes(v reflect.Value, m map[reflect.Type]struct{}) { 60 | if !v.IsValid() { 61 | return 62 | } 63 | switch v.Kind() { 64 | case reflect.Ptr: 65 | if !v.IsNil() { 66 | structTypes(v.Elem(), m) 67 | } 68 | case reflect.Interface: 69 | if !v.IsNil() { 70 | structTypes(v.Elem(), m) 71 | } 72 | case reflect.Slice, reflect.Array: 73 | for i := 0; i < v.Len(); i++ { 74 | structTypes(v.Index(i), m) 75 | } 76 | case reflect.Map: 77 | for _, k := range v.MapKeys() { 78 | structTypes(v.MapIndex(k), m) 79 | } 80 | case reflect.Struct: 81 | m[v.Type()] = struct{}{} 82 | for i := 0; i < v.NumField(); i++ { 83 | structTypes(v.Field(i), m) 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/asset.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Asset requesting Native assests 6 | type Asset struct { 7 | ID int `json:"id"` 8 | Img Img `json:"img"` 9 | Title Title `json:"title"` 10 | Data Data `json:"data"` 11 | Required int `json:"required"` // should default to 1 12 | } 13 | 14 | // MarshalJSONObject implements MarshalerJSONObject 15 | func (a *Asset) MarshalJSONObject(enc *gojay.Encoder) { 16 | enc.IntKey("id", a.ID) 17 | enc.ObjectKey("img", &a.Img) 18 | enc.ObjectKey("title", &a.Title) 19 | enc.ObjectKey("data", &a.Data) 20 | enc.IntKey("required", a.Required) 21 | } 22 | 23 | // IsNil checks if instance is nil 24 | func (a *Asset) IsNil() bool { 25 | return a == nil 26 | } 27 | 28 | // Assets ... 29 | type Assets []Asset 30 | 31 | // MarshalJSONArray ... 32 | func (s Assets) MarshalJSONArray(enc *gojay.Encoder) { 33 | for i := range s { 34 | enc.Object(&s[i]) 35 | } 36 | } 37 | 38 | // IsNil ... 39 | func (s Assets) IsNil() bool { 40 | return len(s) == 0 41 | } 42 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/data.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Data .Type 6 | // 1 sponsored Sponsored By message whereresponse should contain the brandname of the sponsor.text Required. Max 25or longer. 7 | // 2 desc Descriptive text associated with theproduct or service being advertised.Longer length of text in responsemay be truncated or ellipsed by theexchange. text Recommended. Max 140 or longer. 8 | // 3 rating Rating of the product being offeredto the user. For example an app’srating in an app store from 0-5.numberformatted asstringOptional. 0-5integer formattedas string. 9 | // 4 likes Number of social ratings or “likes” ofthe product being offered to theuser.numberformatted asstring 10 | // 5 downloads Number downloads/installs of thisproductnumberformatted asstring 11 | // Data returns contextual data about the Native asset 12 | type Data struct { 13 | Type int `json:"type"` // should be 2 for most cases 14 | Len int `json:"len"` 15 | } 16 | 17 | // MarshalJSONObject implements MarshalerJSONObject 18 | func (d *Data) MarshalJSONObject(enc *gojay.Encoder) { 19 | enc.IntKey("type", d.Type) 20 | enc.IntKey("len", d.Len) 21 | } 22 | 23 | // IsNil checks if instance is nil 24 | func (d *Data) IsNil() bool { 25 | return d == nil 26 | } 27 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/img.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Img .Type 6 | // 1 Icon Icon image Optional.max height: at least 50aspect ratio: 1:1 7 | // 2 Logo Logo image for thebrand/app.To be deprecated in future version- use type 1 Icon. 8 | // 3 Main Large image preview for theadAt least one of 2 size variantsrequired:Small Variant:max height: at least 200max width: at least 200,267, or 382aspect ratio: 1:1, 4:3, or1.91:1Large Variant:max height: at least 627max width: at least 627,836, or 1198aspect ratio: 1:1, 4:3, or1.91:1 9 | // 500+ XXX Reserved for Exchangespecific usage numberedabove 500 No recommendations 10 | // Img requesting types 11 | type Img struct { 12 | Hmin int `json:"hmin"` 13 | Type int `json:"type"` // should be 3 for most cases 14 | Wmin int `json:"wmin"` 15 | Mimes []string `json:"mimes"` 16 | } 17 | 18 | // MarshalJSONObject implements MarshalerJSONObject 19 | func (i *Img) MarshalJSONObject(enc *gojay.Encoder) { 20 | enc.IntKey("hmin", i.Hmin) 21 | enc.IntKey("type", i.Type) 22 | enc.IntKey("wmin", i.Wmin) 23 | var mimes = Strings(i.Mimes) 24 | enc.ArrayKeyOmitEmpty("mimes", mimes) 25 | 26 | } 27 | 28 | // IsNil checks if instance is nil 29 | func (i *Img) IsNil() bool { 30 | return i == nil 31 | } 32 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/primitives.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Strings ... 6 | type Strings []string 7 | 8 | // MarshalJSONArray encodes arrays into JSON 9 | func (a Strings) MarshalJSONArray(enc *gojay.Encoder) { 10 | for _, item := range a { 11 | enc.String(item) 12 | } 13 | } 14 | 15 | // IsNil checks if array is nil 16 | func (a Strings) IsNil() bool { 17 | return len(a) == 0 18 | } 19 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/request.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import ( 4 | "github.com/francoispqt/gojay" 5 | ) 6 | 7 | // Version of the request string 8 | const Version = "1.1" 9 | 10 | // Request is the structure for the 1.1 json string request in the RTB spec 11 | type Request struct { 12 | Assets []Asset `json:"assets"` 13 | Plcmttype int `json:"plcmttype"` 14 | Plcmtcnt int `json:"plcmtcnt"` 15 | Required int `json:"required"` // should default to 1 16 | Ver string `json:"ver"` 17 | } 18 | 19 | // MarshalJSONObject implements MarshalerJSONObject 20 | func (r *Request) MarshalJSONObject(enc *gojay.Encoder) { 21 | var assetSlice = Assets(r.Assets) 22 | enc.ArrayKey("assets", assetSlice) 23 | enc.IntKey("plcmttype", r.Plcmttype) 24 | enc.IntKey("plcmtcnt", r.Plcmtcnt) 25 | enc.IntKey("required", r.Required) 26 | enc.StringKey("ver", r.Ver) 27 | } 28 | 29 | // IsNil checks if instance is nil 30 | func (r *Request) IsNil() bool { 31 | return r == nil 32 | } 33 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/request_test.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "testing" 7 | 8 | "github.com/francoispqt/gojay" 9 | "github.com/google/go-cmp/cmp" 10 | ) 11 | 12 | func TestBidRequestMarshalling(t *testing.T) { 13 | request := Request{ 14 | Plcmttype: 11, 15 | Plcmtcnt: 1, 16 | Ver: Version, 17 | Required: 1, 18 | Assets: []Asset{ 19 | Asset{ 20 | ID: 1, 21 | Img: Img{ 22 | Hmin: 320, 23 | Type: 3, 24 | Wmin: 480, 25 | Mimes: []string{ 26 | "image/jpeg", 27 | "image/png", 28 | "image/gif", 29 | }, 30 | }, 31 | Title: Title{ 32 | Len: 140, 33 | }, 34 | Data: Data{ 35 | Type: 2, 36 | Len: 140, 37 | }, 38 | Required: 1, 39 | }, 40 | }, 41 | } 42 | 43 | tests := []struct { 44 | name string 45 | bidRequest Request 46 | }{ 47 | { 48 | name: "json marshal and gojay marshal should output the same way", 49 | bidRequest: request, 50 | }, 51 | } 52 | 53 | for _, tt := range tests { 54 | t.Run(tt.name, func(t *testing.T) { 55 | regJSON, err := json.Marshal(tt.bidRequest) 56 | if err != nil { 57 | t.Fatalf("json.Marshal failed %v", err) 58 | } 59 | 60 | b := new(bytes.Buffer) 61 | enc := gojay.BorrowEncoder(b) 62 | err = enc.Encode(&request) 63 | defer enc.Release() 64 | if err != nil { 65 | t.Fatalf("gojay.Marshal failed %v", err) 66 | } 67 | gojayJSON := b.Bytes() 68 | 69 | if !cmp.Equal(regJSON, gojayJSON) { 70 | t.Errorf("TestBidRequestMarshalling()\ndiff\n%+v", cmp.Diff(string(regJSON), string(gojayJSON))) 71 | } 72 | }) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /go/native-builder/oneone/request/title.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Title being represent ensure Title metadata on the image 6 | type Title struct { 7 | Len int `json:"len"` 8 | } 9 | 10 | // MarshalJSONObject implements MarshalerJSONObject 11 | func (t *Title) MarshalJSONObject(enc *gojay.Encoder) { 12 | enc.IntKey("len", t.Len) 13 | 14 | } 15 | 16 | // IsNil checks if instance is nil 17 | func (t *Title) IsNil() bool { 18 | return t == nil 19 | } 20 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/app.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // App object should be included if the ad supported content is a non-browser application (typically in 6 | // mobile) as opposed to a website. A bid request must not contain both an App and a Site object. At a 7 | // minimum, it is useful to provide an App ID or bundle, but this is not strictly required 8 | type App struct { 9 | Name string `json:"name" valid:"required"` 10 | Bundle string `json:"bundle" valid:"required"` 11 | Domain string `json:"domain" valid:"required"` 12 | StoreURL string `json:"storeurl" valid:"required"` 13 | Cat []string `json:"cat,omitempty" valid:"optional"` 14 | SectionCat []string `json:"sectioncat,omitempty" valid:"optional"` 15 | PageCat []string `json:"pagecat,omitempty" valid:"optional"` 16 | Ver string `json:"ver,omitempty" valid:"optional"` 17 | PrivacyPolicy int `json:"privacypolicy" valid:"range(0|1),optional"` // no policy 0 policy 1 18 | Paid int `json:"paid" valid:"range(0|1),optional"` // free 0 paid 1 19 | Publisher Publisher `json:"publisher" valid:"required"` 20 | } 21 | 22 | // MarshalJSONObject implements MarshalerJSONObject 23 | func (a *App) MarshalJSONObject(enc *gojay.Encoder) { 24 | enc.StringKey("name", a.Name) 25 | enc.StringKey("bundle", a.Bundle) 26 | enc.StringKey("domain", a.Domain) 27 | enc.StringKey("storeurl", a.StoreURL) 28 | var catSlice = Strings(a.Cat) 29 | enc.ArrayKeyOmitEmpty("cat", catSlice) 30 | var sectionCatSlice = Strings(a.SectionCat) 31 | enc.ArrayKeyOmitEmpty("sectioncat", sectionCatSlice) 32 | var pageCatSlice = Strings(a.PageCat) 33 | enc.ArrayKeyOmitEmpty("pagecat", pageCatSlice) 34 | enc.StringKeyOmitEmpty("ver", a.Ver) 35 | enc.IntKey("privacypolicy", a.PrivacyPolicy) 36 | enc.IntKey("paid", a.Paid) 37 | enc.ObjectKey("publisher", &a.Publisher) 38 | } 39 | 40 | // IsNil checks if instance is nil 41 | func (a *App) IsNil() bool { 42 | return a == nil 43 | } 44 | 45 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 46 | func (a *App) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 47 | 48 | switch k { 49 | case "name": 50 | return dec.String(&a.Name) 51 | 52 | case "bundle": 53 | return dec.String(&a.Bundle) 54 | 55 | case "domain": 56 | return dec.String(&a.Domain) 57 | 58 | case "storeurl": 59 | return dec.String(&a.StoreURL) 60 | 61 | case "cat": 62 | var aSlice = Strings{} 63 | err := dec.Array(&aSlice) 64 | if err == nil && len(aSlice) > 0 { 65 | a.Cat = []string(aSlice) 66 | } 67 | return err 68 | 69 | case "sectioncat": 70 | var aSlice = Strings{} 71 | err := dec.Array(&aSlice) 72 | if err == nil && len(aSlice) > 0 { 73 | a.SectionCat = []string(aSlice) 74 | } 75 | return err 76 | 77 | case "pagecat": 78 | var aSlice = Strings{} 79 | err := dec.Array(&aSlice) 80 | if err == nil && len(aSlice) > 0 { 81 | a.PageCat = []string(aSlice) 82 | } 83 | return err 84 | 85 | case "ver": 86 | return dec.String(&a.Ver) 87 | 88 | case "privacypolicy": 89 | return dec.Int(&a.PrivacyPolicy) 90 | 91 | case "paid": 92 | return dec.Int(&a.Paid) 93 | 94 | case "publisher": 95 | err := dec.Object(&a.Publisher) 96 | return err 97 | 98 | } 99 | return nil 100 | } 101 | 102 | // NKeys returns the number of keys to unmarshal 103 | func (a *App) NKeys() int { return 0 } 104 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/aps.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // APS is the response Object the APS sdk generates 6 | type APS struct { 7 | AmznB []string `json:"amzn_b" valid:"optional"` 8 | AmznVid []string `json:"amzn_vid" valid:"optional"` 9 | AmznH []string `json:"amzn_h" valid:"optional"` 10 | Amznp []string `json:"amznp" valid:"optional"` 11 | Amznrdr []string `json:"amznrdr" valid:"optional"` 12 | Amznslots []string `json:"amznslots" valid:"optional"` 13 | Dc []string `json:"dc" valid:"optional"` 14 | } 15 | 16 | // MarshalJSONObject implements MarshalerJSONObject 17 | func (s *APS) MarshalJSONObject(enc *gojay.Encoder) { 18 | var amznBSlice = Strings(s.AmznB) 19 | enc.ArrayKey("amzn_b", amznBSlice) 20 | var amznVidSlice = Strings(s.AmznVid) 21 | enc.ArrayKey("amzn_vid", amznVidSlice) 22 | var amznHSlice = Strings(s.AmznH) 23 | enc.ArrayKey("amzn_h", amznHSlice) 24 | var amznpSlice = Strings(s.Amznp) 25 | enc.ArrayKey("amznp", amznpSlice) 26 | var amznrdrSlice = Strings(s.Amznrdr) 27 | enc.ArrayKey("amznrdr", amznrdrSlice) 28 | var amznslotsSlice = Strings(s.Amznslots) 29 | enc.ArrayKey("amznslots", amznslotsSlice) 30 | var dcSlice = Strings(s.Dc) 31 | enc.ArrayKey("dc", dcSlice) 32 | } 33 | 34 | // IsNil checks if instance is nil 35 | func (s *APS) IsNil() bool { 36 | return s == nil 37 | } 38 | 39 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 40 | func (s *APS) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 41 | 42 | switch k { 43 | case "amzn_b": 44 | var aSlice = Strings{} 45 | err := dec.Array(&aSlice) 46 | if err == nil && len(aSlice) > 0 { 47 | s.AmznB = []string(aSlice) 48 | } 49 | return err 50 | 51 | case "amzn_vid": 52 | var aSlice = Strings{} 53 | err := dec.Array(&aSlice) 54 | if err == nil && len(aSlice) > 0 { 55 | s.AmznVid = []string(aSlice) 56 | } 57 | return err 58 | 59 | case "amzn_h": 60 | var aSlice = Strings{} 61 | err := dec.Array(&aSlice) 62 | if err == nil && len(aSlice) > 0 { 63 | s.AmznH = []string(aSlice) 64 | } 65 | return err 66 | 67 | case "amznp": 68 | var aSlice = Strings{} 69 | err := dec.Array(&aSlice) 70 | if err == nil && len(aSlice) > 0 { 71 | s.Amznp = []string(aSlice) 72 | } 73 | return err 74 | 75 | case "amznrdr": 76 | var aSlice = Strings{} 77 | err := dec.Array(&aSlice) 78 | if err == nil && len(aSlice) > 0 { 79 | s.Amznrdr = []string(aSlice) 80 | } 81 | return err 82 | 83 | case "amznslots": 84 | var aSlice = Strings{} 85 | err := dec.Array(&aSlice) 86 | if err == nil && len(aSlice) > 0 { 87 | s.Amznslots = []string(aSlice) 88 | } 89 | return err 90 | 91 | case "dc": 92 | var aSlice = Strings{} 93 | err := dec.Array(&aSlice) 94 | if err == nil && len(aSlice) > 0 { 95 | s.Dc = []string(aSlice) 96 | } 97 | return err 98 | 99 | } 100 | return nil 101 | } 102 | 103 | // NKeys returns the number of keys to unmarshal 104 | func (s *APS) NKeys() int { return 0 } 105 | 106 | // APSs ... 107 | type APSs []APS 108 | 109 | // UnmarshalJSONArray ... 110 | func (s *APSs) UnmarshalJSONArray(dec *gojay.Decoder) error { 111 | var value = APS{} 112 | if err := dec.Object(&value); err != nil { 113 | return err 114 | } 115 | *s = append(*s, value) 116 | return nil 117 | } 118 | 119 | // MarshalJSONArray ... 120 | func (s APSs) MarshalJSONArray(enc *gojay.Encoder) { 121 | for i := range s { 122 | enc.Object(&s[i]) 123 | } 124 | } 125 | 126 | // IsNil ... 127 | func (s APSs) IsNil() bool { 128 | return len(s) == 0 129 | } 130 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/aps_custom_unmarshaller.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "strings" 7 | 8 | "github.com/francoispqt/gojay" 9 | ) 10 | 11 | // UnmarshalJSON handles mixed content from APS SDK, this silently fails so that Nimbus's auctions are uneffected if APS changes the data structures underneath 12 | func (a *APS) UnmarshalJSON(b []byte) error { 13 | var rawData map[string]interface{} 14 | err := json.Unmarshal(b, &rawData) 15 | if err != nil { 16 | return nil 17 | } 18 | 19 | writeJSON := func(buf *bytes.Buffer, key string, value []interface{}) { 20 | buf.WriteString(`"` + key + `":[`) 21 | for i, v := range value { 22 | buf.WriteString(`"` + v.(string) + `"`) 23 | if i+1 < len(value) { 24 | buf.WriteByte(',') 25 | } 26 | } 27 | buf.WriteString(`]`) 28 | } 29 | 30 | // allocate the buffer upfront 31 | buf := bytes.NewBuffer(make([]byte, 0, len(b))) 32 | buf.WriteByte('{') 33 | 34 | i, keysN := 1, len(rawData) 35 | for key, value := range rawData { 36 | switch rawData[key].(type) { 37 | case []interface{}: 38 | writeJSON(buf, key, value.([]interface{})) 39 | case string: 40 | // handle the case where the SDK sends seperated values 41 | parts := strings.Split(value.(string), ",") 42 | if len(parts) == 1 && len(parts[0]) == 0 { 43 | parts = []string{} 44 | } 45 | 46 | // create an interface slice for the method, for the most part this will always be a slice of 1 47 | slice := make([]interface{}, len(parts)) 48 | for i := 0; i < len(parts); i++ { 49 | slice[i] = parts[i] 50 | } 51 | writeJSON(buf, key, slice) 52 | } 53 | if i < keysN { 54 | buf.WriteByte(',') 55 | i++ 56 | } 57 | } 58 | buf.WriteByte('}') 59 | 60 | err = gojay.UnmarshalJSONObject(buf.Bytes(), a) 61 | if err != nil { 62 | // avoid infinate recursion, create a type alias 63 | type temp APS 64 | var tempAPS temp 65 | err = json.Unmarshal(buf.Bytes(), &tempAPS) 66 | if err != nil { 67 | return nil 68 | } 69 | // mutate a 70 | *a = APS(tempAPS) 71 | } 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/banner.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import ( 4 | "github.com/francoispqt/gojay" 5 | ) 6 | 7 | // Banner represents the most general type of impression. Although the term “banner” may have very 8 | // specific meaning in other contexts, here it can be many things including a simple static image, an 9 | // expandable ad unit, or even in-banner video (refer to the Video object in Section 3.2.4 for the more 10 | // generalized and full featured video ad units). An array of Banner objects can also appear within the 11 | // Video to describe optional companion ads defined in the VAST specification. 12 | type Banner struct { 13 | BidFloor *float64 `json:"bidfloor,omitempty" valid:"optional"` 14 | BAttr []int `json:"battr,omitempty" valid:"optional"` 15 | Format []Format `json:"format,omitempty" valid:"optional"` 16 | W int `json:"w" valid:"required"` 17 | H int `json:"h" valid:"required"` 18 | API []int `json:"api,omitempty" valid:"inintarr(1|2|3|4|5|6|7),optional"` // 3,5,6 -> mraid1, 2, and 3 19 | Pos int `json:"pos,omitempty" valid:"range(0|7),optional"` // 0,1,2,3,4,5,6,7 -> Unknown, Above the Fold, DEPRECATED - May or may not be initially visible depending on screen size/resolution.,Below the Fold,Header,Footer,Sidebar,Full Screen 20 | Vcm int `json:"vcm,omitempty" valid:"optional"` // Relevant only for Banner objects used with a Video object (Section 3.2.7) in an array of companion ads. Indicates the companion banner rendering mode relative to the associated video, where 0 = concurrent, 1 = end-card. 21 | } 22 | 23 | // MarshalJSONObject implements MarshalerJSONObject 24 | func (b *Banner) MarshalJSONObject(enc *gojay.Encoder) { 25 | if b.BidFloor != nil { 26 | enc.Float64KeyOmitEmpty("bidfloor", *b.BidFloor) 27 | } 28 | var battrSlice = Ints(b.BAttr) 29 | enc.ArrayKeyOmitEmpty("battr", battrSlice) 30 | var formatSlice = Formats(b.Format) 31 | enc.ArrayKeyOmitEmpty("format", formatSlice) 32 | enc.IntKeyOmitEmpty("w", b.W) 33 | enc.IntKeyOmitEmpty("h", b.H) 34 | enc.IntKeyOmitEmpty("pos", b.Pos) 35 | var aPISlice = Ints(b.API) 36 | enc.ArrayKeyOmitEmpty("api", aPISlice) 37 | enc.IntKeyOmitEmpty("vcm", b.Vcm) 38 | } 39 | 40 | // IsNil checks if instance is nil 41 | func (b *Banner) IsNil() bool { 42 | return b == nil 43 | } 44 | 45 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 46 | func (b *Banner) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 47 | 48 | switch k { 49 | 50 | case "bidfloor": 51 | var value float64 52 | err := dec.Float64(&value) 53 | if err == nil { 54 | b.BidFloor = &value 55 | } 56 | return err 57 | 58 | case "format": 59 | var aSlice = Formats{} 60 | err := dec.Array(&aSlice) 61 | if err == nil && len(aSlice) > 0 { 62 | b.Format = []Format(aSlice) 63 | } 64 | return err 65 | 66 | case "battr": 67 | var aSlice = Ints{} 68 | err := dec.Array(&aSlice) 69 | if err == nil && len(aSlice) > 0 { 70 | b.BAttr = []int(aSlice) 71 | } 72 | return err 73 | 74 | case "w": 75 | return dec.Int(&b.W) 76 | 77 | case "h": 78 | return dec.Int(&b.H) 79 | 80 | case "pos": 81 | return dec.Int(&b.Pos) 82 | 83 | case "api": 84 | var aSlice = Ints{} 85 | err := dec.Array(&aSlice) 86 | if err == nil && len(aSlice) > 0 { 87 | b.API = []int(aSlice) 88 | } 89 | return err 90 | 91 | case "vcm": 92 | return dec.Int(&b.Vcm) 93 | 94 | } 95 | return nil 96 | } 97 | 98 | // NKeys returns the number of keys to unmarshal 99 | func (b *Banner) NKeys() int { return 0 } 100 | 101 | // Banners ... 102 | type Banners []Banner 103 | 104 | // UnmarshalJSONArray ... 105 | func (s *Banners) UnmarshalJSONArray(dec *gojay.Decoder) error { 106 | var value = Banner{} 107 | if err := dec.Object(&value); err != nil { 108 | return err 109 | } 110 | *s = append(*s, value) 111 | return nil 112 | } 113 | 114 | // MarshalJSONArray ... 115 | func (s Banners) MarshalJSONArray(enc *gojay.Encoder) { 116 | for i := range s { 117 | enc.Object(&s[i]) 118 | } 119 | } 120 | 121 | // IsNil ... 122 | func (s Banners) IsNil() bool { 123 | return len(s) == 0 124 | } 125 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/data.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Data and Segment objects together allow additional data about the user to be specified. This data 6 | // may be from multiple sources whether from the exchange itself or third party providers as specified by 7 | // the id field. A bid request can mix data objects from multiple providers. The specific data providers in 8 | // use should be published by the exchange a priori to its bidders. 9 | type Data struct { 10 | ID string `json:"id,omitempty" valid:"optional"` 11 | Name string `json:"name,omitempty" valid:"optional"` 12 | Segment []Segment `json:"segment,omitempty" valid:"optional"` 13 | } 14 | 15 | // MarshalJSONObject implements MarshalerJSONObject 16 | func (d *Data) MarshalJSONObject(enc *gojay.Encoder) { 17 | enc.StringKeyOmitEmpty("id", d.ID) 18 | enc.StringKeyOmitEmpty("name", d.Name) 19 | var segmentSlice = Segments(d.Segment) 20 | enc.ArrayKeyOmitEmpty("segment", segmentSlice) 21 | } 22 | 23 | // IsNil checks if instance is nil 24 | func (d *Data) IsNil() bool { 25 | return d == nil 26 | } 27 | 28 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 29 | func (d *Data) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 30 | 31 | switch k { 32 | case "id": 33 | return dec.String(&d.ID) 34 | 35 | case "name": 36 | return dec.String(&d.Name) 37 | 38 | case "segment": 39 | var aSlice = Segments{} 40 | err := dec.Array(&aSlice) 41 | if err == nil && len(aSlice) > 0 { 42 | d.Segment = []Segment(aSlice) 43 | } 44 | return err 45 | 46 | } 47 | return nil 48 | } 49 | 50 | // NKeys returns the number of keys to unmarshal 51 | func (d *Data) NKeys() int { return 0 } 52 | 53 | // Datas ... 54 | type Datas []Data 55 | 56 | // UnmarshalJSONArray ... 57 | func (s *Datas) UnmarshalJSONArray(dec *gojay.Decoder) error { 58 | var value = Data{} 59 | if err := dec.Object(&value); err != nil { 60 | return err 61 | } 62 | *s = append(*s, value) 63 | return nil 64 | } 65 | 66 | // MarshalJSONArray ... 67 | func (s Datas) MarshalJSONArray(enc *gojay.Encoder) { 68 | for i := range s { 69 | enc.Object(&s[i]) 70 | } 71 | } 72 | 73 | // IsNil ... 74 | func (s Datas) IsNil() bool { 75 | return len(s) == 0 76 | } 77 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/facebook_test_ad_types.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | type FacebookTestAdType string 4 | 5 | // below are constants that can used to change the ad demo type in the Facebook response 6 | // for more information on the details of each demo type and requirements see the Facebook documentation in the below link 7 | // https://developers.facebook.com/docs/audience-network/overview/in-house-mediation/server-to-server/testing 8 | const ( 9 | VideoLandscapeAppInstall46Seconds FacebookTestAdType = "VID_HD_16_9_46S_APP_INSTALL" 10 | VideoLandscapeLink46Seconds = "VID_HD_16_9_46S_LINK" 11 | VideoLandscapeAppInstall15Seconds = "VID_HD_16_9_15S_APP_INSTALL" 12 | VideoLandscapeLink15Seconds = "VID_HD_16_9_15S_LINK" 13 | VideoPortraitAppInstall39Seconds = "VID_HD_9_16_39S_APP_INSTALL" 14 | VideoPortraitLink39Seconds = "VID_HD_9_16_39S_LINK" 15 | ImageLandscapeAppInstall = "IMG_16_9_APP_INSTALL" 16 | ImageLandscapeLink = "IMG_16_9_LINK" 17 | CarouselImageAppInstall = "CAROUSEL_IMG_SQUARE_APP_INSTALL" 18 | CarouselImageLink = "CAROUSEL_IMG_SQUARE_LINK" 19 | ) 20 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/format.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Format object represents an allowed size (i.e., height and width combination) for a banner impression. 6 | // These are typically used in an array for an impression where multiple sizes are permitted. 7 | type Format struct { 8 | W int `json:"w" valid:"required"` 9 | H int `json:"h" valid:"required"` 10 | } 11 | 12 | // MarshalJSONObject implements MarshalerJSONObject 13 | func (f *Format) MarshalJSONObject(enc *gojay.Encoder) { 14 | enc.IntKeyOmitEmpty("w", f.W) 15 | enc.IntKeyOmitEmpty("h", f.H) 16 | } 17 | 18 | // IsNil checks if instance is nil 19 | func (f *Format) IsNil() bool { 20 | return f == nil 21 | } 22 | 23 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 24 | func (f *Format) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 25 | 26 | switch k { 27 | case "w": 28 | return dec.Int(&f.W) 29 | 30 | case "h": 31 | return dec.Int(&f.H) 32 | 33 | } 34 | return nil 35 | } 36 | 37 | // NKeys returns the number of keys to unmarshal 38 | func (f *Format) NKeys() int { return 0 } 39 | 40 | // Formats ... 41 | type Formats []Format 42 | 43 | // UnmarshalJSONArray ... 44 | func (s *Formats) UnmarshalJSONArray(dec *gojay.Decoder) error { 45 | var value = Format{} 46 | if err := dec.Object(&value); err != nil { 47 | return err 48 | } 49 | *s = append(*s, value) 50 | return nil 51 | } 52 | 53 | // MarshalJSONArray ... 54 | func (s Formats) MarshalJSONArray(enc *gojay.Encoder) { 55 | for i := range s { 56 | enc.Object(&s[i]) 57 | } 58 | } 59 | 60 | // IsNil ... 61 | func (s Formats) IsNil() bool { 62 | return len(s) == 0 63 | } 64 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/geo.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Geo object encapsulates various methods for specifying a geographic location. When subordinate to a 6 | // Device object, it indicates the location of the device which can also be interpreted as the user’s current 7 | // location. When subordinate to a User object, it indicates the location of the user’s home base (i.e., not 8 | // necessarily their current location). 9 | type Geo struct { 10 | Lat float64 `json:"lat,omitempty" valid:"required"` 11 | Lon float64 `json:"lon,omitempty" valid:"required"` 12 | Type int `json:"type,omitempty" valid:"range(1|3),optional"` // 1,2,3 -> GPS/Location Services, IP Address, User provided (e.g., registration data) 13 | IPService int `json:"ipservice,omitempty" valid:"range(1|4),optional"` // 1,2,3,4 -> ip2location, Neustar (Quova), MaxMind, NetAcuity (Digital Element) 14 | Country string `json:"country,omitempty" valid:"ISO3166Alpha3,optional"` // alpha 3 15 | City string `json:"city,omitempty" valid:"optional"` 16 | Metro string `json:"metro,omitempty" valid:"optional"` 17 | State string `json:"state,omitempty" valid:"optional"` 18 | } 19 | 20 | // MarshalJSONObject implements MarshalerJSONObject 21 | func (g *Geo) MarshalJSONObject(enc *gojay.Encoder) { 22 | enc.Float64KeyOmitEmpty("lat", g.Lat) 23 | enc.Float64KeyOmitEmpty("lon", g.Lon) 24 | enc.IntKeyOmitEmpty("type", g.Type) 25 | enc.IntKeyOmitEmpty("ipservice", g.IPService) 26 | enc.StringKeyOmitEmpty("country", g.Country) 27 | enc.StringKeyOmitEmpty("city", g.City) 28 | enc.StringKeyOmitEmpty("metro", g.Metro) 29 | enc.StringKeyOmitEmpty("state", g.State) 30 | } 31 | 32 | // IsNil checks if instance is nil 33 | func (g *Geo) IsNil() bool { 34 | return g == nil 35 | } 36 | 37 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 38 | func (g *Geo) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 39 | 40 | switch k { 41 | case "lat": 42 | return dec.Float64(&g.Lat) 43 | 44 | case "lon": 45 | return dec.Float64(&g.Lon) 46 | 47 | case "type": 48 | return dec.Int(&g.Type) 49 | 50 | case "ipservice": 51 | return dec.Int(&g.IPService) 52 | 53 | case "country": 54 | return dec.String(&g.Country) 55 | 56 | case "city": 57 | return dec.String(&g.City) 58 | 59 | case "metro": 60 | return dec.String(&g.Metro) 61 | 62 | case "state": 63 | return dec.String(&g.State) 64 | 65 | } 66 | return nil 67 | } 68 | 69 | // NKeys returns the number of keys to unmarshal 70 | func (g *Geo) NKeys() int { return 0 } 71 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/identity_link.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // EID is a higher level wrapper for vendor identifiers 6 | type EID struct { 7 | Source string `json:"source"` 8 | UIDS UIDS `json:"uids"` 9 | } 10 | 11 | // MarshalJSONObject implements MarshalerJSONObject 12 | func (e *EID) MarshalJSONObject(enc *gojay.Encoder) { 13 | enc.StringKeyOmitEmpty("source", e.Source) 14 | enc.ArrayKeyOmitEmpty("uids", e.UIDS) 15 | } 16 | 17 | // IsNil checks if instance is nil 18 | func (e *EID) IsNil() bool { 19 | return e == nil 20 | } 21 | 22 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 23 | func (e *EID) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 24 | switch k { 25 | case "source": 26 | return dec.String(&e.Source) 27 | 28 | case "uids": 29 | var aSlice = UIDS{} 30 | err := dec.Array(&aSlice) 31 | if err == nil && len(aSlice) > 0 { 32 | e.UIDS = aSlice 33 | } 34 | return err 35 | } 36 | return nil 37 | } 38 | 39 | // NKeys returns the number of keys to unmarshal, by returning 0 we are saying to return all keys for marshalling 40 | func (e *EID) NKeys() int { return 0 } 41 | 42 | // EIDS defines a slice of EID 43 | type EIDS []EID 44 | 45 | // UnmarshalJSONArray implements gojay's array Unmarshaler 46 | func (e *EIDS) UnmarshalJSONArray(dec *gojay.Decoder) error { 47 | var value = EID{} 48 | if err := dec.Object(&value); err != nil { 49 | return err 50 | } 51 | *e = append(*e, value) 52 | return nil 53 | } 54 | 55 | // MarshalJSONArray ... 56 | func (e EIDS) MarshalJSONArray(enc *gojay.Encoder) { 57 | for i := range e { 58 | enc.Object(&e[i]) 59 | } 60 | } 61 | 62 | // IsNil checks if instance is nil 63 | func (e EIDS) IsNil() bool { 64 | return len(e) == 0 65 | } 66 | 67 | // UID defines metadata for vendors 68 | type UID struct { 69 | ID string `json:"id"` 70 | Ext *IdentityExt `json:"ext"` 71 | } 72 | 73 | // MarshalJSONObject implements MarshalerJSONObject 74 | func (u *UID) MarshalJSONObject(enc *gojay.Encoder) { 75 | enc.StringKeyOmitEmpty("id", u.ID) 76 | enc.ObjectKeyOmitEmpty("ext", u.Ext) 77 | } 78 | 79 | // IsNil checks if instance is nil 80 | func (u *UID) IsNil() bool { 81 | return u == nil 82 | } 83 | 84 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 85 | func (u *UID) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 86 | switch k { 87 | case "id": 88 | return dec.String(&u.ID) 89 | 90 | case "ext": 91 | var identityExt IdentityExt 92 | err := dec.Object(&identityExt) 93 | if err == nil { 94 | u.Ext = &identityExt 95 | } 96 | return err 97 | } 98 | return nil 99 | } 100 | 101 | // NKeys returns the number of keys to unmarshal, by returning 0 we are saying to return all keys for marshalling 102 | func (u *UID) NKeys() int { return 0 } 103 | 104 | // UIDS defines a slice of UID 105 | type UIDS []UID 106 | 107 | // UnmarshalJSONArray implements gojay's array Unmarshaler 108 | func (u *UIDS) UnmarshalJSONArray(dec *gojay.Decoder) error { 109 | var value = UID{} 110 | if err := dec.Object(&value); err != nil { 111 | return err 112 | } 113 | *u = append(*u, value) 114 | return nil 115 | } 116 | 117 | // MarshalJSONArray ... 118 | func (u UIDS) MarshalJSONArray(enc *gojay.Encoder) { 119 | for i := range u { 120 | enc.Object(&u[i]) 121 | } 122 | } 123 | 124 | // IsNil provides on abstraction to determine if the object is empty 125 | func (u UIDS) IsNil() bool { 126 | return len(u) == 0 127 | } 128 | 129 | type IdentityExt struct { 130 | RTIPartner string `json:"rtiPartner"` 131 | } 132 | 133 | // MarshalJSONObject implements MarshalerJSONObject 134 | func (i *IdentityExt) MarshalJSONObject(enc *gojay.Encoder) { 135 | enc.StringKeyOmitEmpty("rtiPartner", i.RTIPartner) 136 | } 137 | 138 | // IsNil checks if instance is nil 139 | func (i *IdentityExt) IsNil() bool { 140 | return i == nil 141 | } 142 | 143 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 144 | func (i *IdentityExt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 145 | switch k { 146 | case "rtiPartner": 147 | return dec.String(&i.RTIPartner) 148 | } 149 | return nil 150 | } 151 | 152 | // NKeys returns the number of keys to unmarshal, by returning 0 we are saying to return all keys for marshalling 153 | func (i *IdentityExt) NKeys() int { return 0 } 154 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/identity_link_test.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "testing" 7 | 8 | "github.com/francoispqt/gojay" 9 | "github.com/google/go-cmp/cmp" 10 | ) 11 | 12 | // https://github.com/Advertising-ID-Consortium/IdentityLink-in-RTB 13 | var _dataExample = ` 14 | [ 15 | { 16 | "source": "liveramp.com", 17 | "uids": [ 18 | { 19 | "id": "XY1000bIVBVah9ium-sZ3ykhPiXQbEcUpn4GjCtxrrw2BRDGM", 20 | "ext": { 21 | "rtiPartner": "idl" 22 | } 23 | } 24 | ] 25 | }, 26 | { 27 | "source": "adserver.org", 28 | "uids": [ 29 | { 30 | "id": "6bca7f6b-a98a-46c0-be05-6020f7604598", 31 | "ext": { 32 | "rtiPartner": "TDID" 33 | } 34 | } 35 | ] 36 | } 37 | ] 38 | ` 39 | 40 | func TestIdentityLinkSerialization(t *testing.T) { 41 | var eidsJSON EIDS 42 | if jErr := json.Unmarshal([]byte(_dataExample), &eidsJSON); jErr != nil { 43 | t.Fatalf("TestIdentityLinkSerialization() Unable to json.Unmarshal %v", eidsJSON) 44 | } 45 | 46 | var eidsGojay EIDS 47 | if jErr := gojay.UnmarshalJSONArray([]byte(_dataExample), &eidsGojay); jErr != nil { 48 | t.Fatalf("TestIdentityLinkSerialization() Unable to gojay.Unmarshal %v", eidsGojay) 49 | } 50 | 51 | if !cmp.Equal(eidsJSON, eidsGojay) { 52 | t.Errorf("TestIdentityLinkSerialization() gojay != standard lib = diff\n %+v", cmp.Diff(eidsJSON, eidsGojay)) 53 | } 54 | 55 | b := new(bytes.Buffer) 56 | enc := gojay.BorrowEncoder(b) 57 | encodeErr := enc.Encode(&eidsGojay) 58 | defer enc.Release() 59 | if encodeErr != nil { 60 | t.Fatalf("TestIdentityLinkSerialization() gojay.Marshal failed %v", encodeErr) 61 | } 62 | gojayBytes := b.Bytes() 63 | wantBytes := bytes.Replace([]byte(_dataExample), []byte(" "), []byte(""), -1) 64 | wantBytes = bytes.Replace(wantBytes, []byte("\n"), []byte(""), -1) 65 | if !cmp.Equal(gojayBytes, wantBytes) { 66 | t.Errorf("TestIdentityLinkSerialization() encoded bytes don't match the expectations diff\n %+v", cmp.Diff(gojayBytes, wantBytes)) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/mobilefuse_data.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import ( 4 | "github.com/francoispqt/gojay" 5 | ) 6 | 7 | type MobileFuseData map[string]string 8 | 9 | // MarshalJSONObject implements MarshalerJSONObject 10 | func (m *MobileFuseData) MarshalJSONObject(enc *gojay.Encoder) { 11 | if m != nil { 12 | for k, v := range *m { 13 | enc.StringKey(k, v) 14 | } 15 | } 16 | } 17 | 18 | // IsNil checks if instance is nil 19 | func (m *MobileFuseData) IsNil() bool { 20 | return m == nil || len(*m) == 0 21 | } 22 | 23 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 24 | func (m *MobileFuseData) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 25 | if m == nil || *m == nil { 26 | *m = make(MobileFuseData) 27 | } 28 | var value string 29 | if err := dec.String(&value); err == nil { 30 | tmp := *m 31 | tmp[k] = value 32 | *m = tmp 33 | } 34 | return nil 35 | } 36 | 37 | // NKeys returns the number of keys to unmarshal 38 | func (m *MobileFuseData) NKeys() int { return 0 } 39 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/native.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Native object represents a native type impression. Native ad units are intended to blend seamlessly into 6 | // the surrounding content (e.g., a sponsored Twitter or Facebook post). As such, the response must be 7 | // well-structured to afford the publisher fine-grained control over rendering. 8 | type Native struct { 9 | ID string `json:"id,omitempty" valid:"optional"` 10 | BidFloor *float64 `json:"bidfloor,omitempty" valid:"optional"` 11 | Request string `json:"request,omitempty" valid:"required"` 12 | Ver string `json:"ver,omitempty" valid:"optional"` 13 | API []int `json:"api,omitempty" valid:"optional"` 14 | Battr []int `json:"battr,omitempty" valid:"optional"` 15 | } 16 | 17 | // MarshalJSONObject implements MarshalerJSONObject 18 | func (n *Native) MarshalJSONObject(enc *gojay.Encoder) { 19 | enc.StringKeyOmitEmpty("id", n.ID) 20 | if n.BidFloor != nil { 21 | enc.Float64KeyOmitEmpty("bidfloor", *n.BidFloor) 22 | } 23 | enc.StringKeyOmitEmpty("request", n.Request) 24 | enc.StringKeyOmitEmpty("ver", n.Ver) 25 | var aPISlice = Ints(n.API) 26 | enc.ArrayKeyOmitEmpty("api", aPISlice) 27 | var battrSlice = Ints(n.Battr) 28 | enc.ArrayKeyOmitEmpty("battr", battrSlice) 29 | } 30 | 31 | // IsNil checks if instance is nil 32 | func (n *Native) IsNil() bool { 33 | return n == nil 34 | } 35 | 36 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 37 | func (n *Native) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 38 | 39 | switch k { 40 | case "id": 41 | return dec.String(&n.ID) 42 | 43 | case "bidfloor": 44 | var value float64 45 | err := dec.Float64(&value) 46 | if err == nil { 47 | n.BidFloor = &value 48 | } 49 | return err 50 | 51 | case "request": 52 | return dec.String(&n.Request) 53 | 54 | case "ver": 55 | return dec.String(&n.Ver) 56 | 57 | case "api": 58 | var aSlice = Ints{} 59 | err := dec.Array(&aSlice) 60 | if err == nil && len(aSlice) > 0 { 61 | n.API = []int(aSlice) 62 | } 63 | return err 64 | 65 | case "battr": 66 | var aSlice = Ints{} 67 | err := dec.Array(&aSlice) 68 | if err == nil && len(aSlice) > 0 { 69 | n.Battr = []int(aSlice) 70 | } 71 | return err 72 | 73 | } 74 | return nil 75 | } 76 | 77 | // NKeys returns the number of keys to unmarshal 78 | func (n *Native) NKeys() int { return 0 } 79 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/primitives.go: -------------------------------------------------------------------------------- 1 | // Slice data structures to work with Gojay 2 | 3 | package twofive 4 | 5 | import ( 6 | "github.com/francoispqt/gojay" 7 | ) 8 | 9 | // Ints ... 10 | type Ints []int 11 | 12 | // UnmarshalJSONArray decodes JSON array elements into slice 13 | func (a *Ints) UnmarshalJSONArray(dec *gojay.Decoder) error { 14 | var value int 15 | if err := dec.Int(&value); err != nil { 16 | return err 17 | } 18 | *a = append(*a, value) 19 | return nil 20 | } 21 | 22 | // MarshalJSONArray encodes arrays into JSON 23 | func (a Ints) MarshalJSONArray(enc *gojay.Encoder) { 24 | for _, item := range a { 25 | enc.Int(item) 26 | } 27 | } 28 | 29 | // IsNil checks if array is nil 30 | func (a Ints) IsNil() bool { 31 | return len(a) == 0 32 | } 33 | 34 | // Strings ... 35 | type Strings []string 36 | 37 | // UnmarshalJSONArray decodes JSON array elements into slice 38 | func (a *Strings) UnmarshalJSONArray(dec *gojay.Decoder) error { 39 | var value string 40 | if err := dec.String(&value); err != nil { 41 | return err 42 | } 43 | *a = append(*a, value) 44 | return nil 45 | } 46 | 47 | // MarshalJSONArray encodes arrays into JSON 48 | func (a Strings) MarshalJSONArray(enc *gojay.Encoder) { 49 | for _, item := range a { 50 | enc.String(item) 51 | } 52 | } 53 | 54 | // IsNil checks if array is nil 55 | func (a Strings) IsNil() bool { 56 | return len(a) == 0 57 | } 58 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/primitives_to_references.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | // FloatPointer is a utility function to return a reference of a float64 4 | func FloatPointer(f float64) *float64 { 5 | return &f 6 | } 7 | 8 | // IntPointer is a utility function to return a reference of a int 9 | func IntPointer(i int) *int { 10 | return &i 11 | } 12 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/publisher.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Publisher object describes the publisher of the media in which the ad will be displayed. The publisher is 6 | // typically the seller in an OpenRTB transaction. 7 | type Publisher struct { 8 | Name string `json:"name" valid:"required"` 9 | Cat []string `json:"cat,omitempty" valid:"optional"` 10 | Domain string `json:"domain" valid:"required"` 11 | } 12 | 13 | // MarshalJSONObject implements MarshalerJSONObject 14 | func (p *Publisher) MarshalJSONObject(enc *gojay.Encoder) { 15 | enc.StringKey("name", p.Name) 16 | var catSlice = Strings(p.Cat) 17 | enc.ArrayKeyOmitEmpty("cat", catSlice) 18 | enc.StringKey("domain", p.Domain) 19 | } 20 | 21 | // IsNil checks if instance is nil 22 | func (p *Publisher) IsNil() bool { 23 | return p == nil 24 | } 25 | 26 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 27 | func (p *Publisher) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 28 | 29 | switch k { 30 | case "name": 31 | return dec.String(&p.Name) 32 | 33 | case "cat": 34 | var aSlice = Strings{} 35 | err := dec.Array(&aSlice) 36 | if err == nil && len(aSlice) > 0 { 37 | p.Cat = []string(aSlice) 38 | } 39 | return err 40 | 41 | case "domain": 42 | return dec.String(&p.Domain) 43 | 44 | } 45 | return nil 46 | } 47 | 48 | // NKeys returns the number of keys to unmarshal 49 | func (p *Publisher) NKeys() int { return 0 } 50 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/regs.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Regs object contains any legal, governmental, or industry regulations that apply to the request. The 6 | // coppa flag signals whether or not the request falls under the United States Federal Trade Commission’s 7 | // regulations for the United States Children’s Online Privacy Protection Act (“COPPA”). 8 | type Regs struct { 9 | Coppa int `json:"coppa" valid:"range(0|1),optional"` 10 | Ext *RegsExt `json:"ext" valid:"optional"` 11 | } 12 | 13 | // RegsExt being used for GDPR, CCPA as US Privacy, and any regulations via the Global Privacy Platform (GPP) 14 | // string. The relevant regulations are specified within the GPP string and GPP Section ID (SID) list. 15 | // GPPSIDs is a comma-separated list of GPP Section IDs. 16 | type RegsExt struct { 17 | GDPR int `json:"gdpr" valid:"range(0|1),optional"` 18 | USPrivacy string `json:"us_privacy,omitempty" valid:"optional"` 19 | GPP string `json:"gpp,omitempty" valid:"optional"` 20 | GPPSIDs string `json:"gpp_sid,omitempty" valid:"optional"` 21 | } 22 | 23 | // MarshalJSONObject implements MarshalerJSONObject 24 | func (r *Regs) MarshalJSONObject(enc *gojay.Encoder) { 25 | enc.IntKey("coppa", r.Coppa) 26 | enc.ObjectKeyNullEmpty("ext", r.Ext) 27 | } 28 | 29 | // IsNil checks if instance is nil 30 | func (r *Regs) IsNil() bool { 31 | return r == nil 32 | } 33 | 34 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 35 | func (r *Regs) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 36 | 37 | switch k { 38 | case "coppa": 39 | return dec.Int(&r.Coppa) 40 | 41 | case "ext": 42 | var regsExt RegsExt 43 | err := dec.Object(®sExt) 44 | if err == nil { 45 | r.Ext = ®sExt 46 | } 47 | return err 48 | 49 | } 50 | return nil 51 | } 52 | 53 | // NKeys returns the number of keys to unmarshal 54 | func (r *Regs) NKeys() int { return 0 } 55 | 56 | // MarshalJSONObject implements MarshalerJSONObject 57 | func (e *RegsExt) MarshalJSONObject(enc *gojay.Encoder) { 58 | enc.IntKey("gdpr", e.GDPR) 59 | enc.StringKeyOmitEmpty("us_privacy", e.USPrivacy) 60 | enc.StringKeyOmitEmpty("gpp", e.GPP) 61 | enc.StringKeyOmitEmpty("gpp_sid", e.GPPSIDs) 62 | } 63 | 64 | // IsNil checks if instance is nil 65 | func (e *RegsExt) IsNil() bool { 66 | return e == nil 67 | } 68 | 69 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 70 | func (e *RegsExt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 71 | 72 | switch k { 73 | case "gdpr": 74 | return dec.Int(&e.GDPR) 75 | case "us_privacy": 76 | return dec.String(&e.USPrivacy) 77 | case "gpp": 78 | return dec.String(&e.GPP) 79 | case "gpp_sid": 80 | return dec.String(&e.GPPSIDs) 81 | } 82 | return nil 83 | } 84 | 85 | // NKeys returns the number of keys to unmarshal 86 | func (e *RegsExt) NKeys() int { return 0 } 87 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/segment.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Segment objects are essentially key-value pairs that convey specific units of data about the user. The 6 | // parent Data object is a collection of such values from a given data provider. The specific segment 7 | // names and value options must be published by the exchange a priori to its bidders. 8 | type Segment struct { 9 | ID string `json:"id,omitempty" valid:"optional"` 10 | Name string `json:"name,omitempty" valid:"optional"` 11 | Value string `json:"value,omitempty" valid:"optional"` 12 | } 13 | 14 | // Segments ... 15 | type Segments []Segment 16 | 17 | // UnmarshalJSONArray ... 18 | func (s *Segments) UnmarshalJSONArray(dec *gojay.Decoder) error { 19 | var value = Segment{} 20 | if err := dec.Object(&value); err != nil { 21 | return err 22 | } 23 | *s = append(*s, value) 24 | return nil 25 | } 26 | 27 | // MarshalJSONArray ... 28 | func (s Segments) MarshalJSONArray(enc *gojay.Encoder) { 29 | for i := range s { 30 | enc.Object(&s[i]) 31 | } 32 | } 33 | 34 | // IsNil ... 35 | func (s Segments) IsNil() bool { 36 | return len(s) == 0 37 | } 38 | 39 | // MarshalJSONObject implements MarshalerJSONObject 40 | func (s *Segment) MarshalJSONObject(enc *gojay.Encoder) { 41 | enc.StringKeyOmitEmpty("id", s.ID) 42 | enc.StringKeyOmitEmpty("name", s.Name) 43 | enc.StringKeyOmitEmpty("value", s.Value) 44 | } 45 | 46 | // IsNil checks if instance is nil 47 | func (s *Segment) IsNil() bool { 48 | return s == nil 49 | } 50 | 51 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 52 | func (s *Segment) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 53 | 54 | switch k { 55 | case "id": 56 | return dec.String(&s.ID) 57 | 58 | case "name": 59 | return dec.String(&s.Name) 60 | 61 | case "value": 62 | return dec.String(&s.Value) 63 | 64 | } 65 | return nil 66 | } 67 | 68 | // NKeys returns the number of keys to unmarshal 69 | func (s *Segment) NKeys() int { return 0 } 70 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/skadn.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Skadn is used for direct SSP to DSP connections where a DSP wants to only consume their own relevant SKAdNetwork IDs. 6 | // Object should only be present if both the SSP SDK version and the OS version (iOS 14.0+) support SKAdNetwork. 7 | type Skadn struct { 8 | Version string `json:"version,omitempty" valid:"optional"` // Version of skadnetwork supported. Always "2.0" or higher. Dependent on both the OS version and the SDK version. 9 | SourceApp string `json:"sourceapp,omitempty" valid:"required"` // ID of publisher app in Apple’s App Store. Should match app.bundle in OpenRTB 2.x and app.storeid in AdCOM 1.x 10 | Skadnetids []string `json:"skadnetids,omitempty" valid:"optional"` // A subset of SKAdNetworkItem entries in the publisher app’s Info.plist that are relevant to the DSP. Recommended that this list not exceed 20. 11 | } 12 | 13 | // MarshalJSONObject implements MarshalerJSONObject 14 | func (s *Skadn) MarshalJSONObject(enc *gojay.Encoder) { 15 | enc.StringKeyOmitEmpty("version", s.Version) 16 | enc.StringKeyOmitEmpty("sourceapp", s.SourceApp) 17 | var bAppSlice = Strings(s.Skadnetids) 18 | enc.ArrayKeyOmitEmpty("skadnetids", bAppSlice) 19 | } 20 | 21 | // IsNil checks if instance is nil 22 | func (s *Skadn) IsNil() bool { 23 | return s == nil 24 | } 25 | 26 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 27 | func (s *Skadn) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 28 | 29 | switch k { 30 | case "version": 31 | return dec.String(&s.Version) 32 | 33 | case "sourceapp": 34 | return dec.String(&s.SourceApp) 35 | 36 | case "skadnetids": 37 | var aSlice = Strings{} 38 | err := dec.Array(&aSlice) 39 | if err == nil && len(aSlice) > 0 { 40 | s.Skadnetids = []string(aSlice) 41 | } 42 | return err 43 | } 44 | return nil 45 | } 46 | 47 | // NKeys returns the number of keys to unmarshal 48 | func (s *Skadn) NKeys() int { return 0 } 49 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/source.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Source describes the nature and behavior of the entity that is the source of the bid request 6 | // upstream from the exchange. The primary purpose of this object is to define post-auction or upstream 7 | // decisioning when the exchange itself does not control the final decision. A common example of this is 8 | // header bidding, but it can also apply to upstream server entities such as another RTB exchange, a 9 | // mediation platform, or an ad server combines direct campaigns with 3rd party demand in decisioning. 10 | type Source struct { 11 | Ext SourceExt `json:"ext,omitempty" valid:"optional"` 12 | } 13 | 14 | // SourceExt also for OM SDK extensions to be passed to demand 15 | type SourceExt struct { 16 | Omidpn string `json:"omidpn,omitempty" valid:"optional"` // identifier of the OM SDK integration, this is the same as the "name" parameter of the OMID Partner object 17 | Omidpv string `json:"omidpv,omitempty" valid:"optional"` // (optional) Version of the OM SDK version 18 | } 19 | 20 | // MarshalJSONObject implements MarshalerJSONObject 21 | func (s *Source) MarshalJSONObject(enc *gojay.Encoder) { 22 | enc.ObjectKeyNullEmpty("ext", &s.Ext) 23 | } 24 | 25 | // IsNil checks if instance is nil 26 | func (s *Source) IsNil() bool { 27 | return s == nil 28 | } 29 | 30 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 31 | func (s *Source) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 32 | 33 | switch k { 34 | case "ext": 35 | return dec.Object(&s.Ext) 36 | 37 | } 38 | return nil 39 | } 40 | 41 | // NKeys returns the number of keys to unmarshal 42 | func (s *Source) NKeys() int { return 0 } 43 | 44 | // MarshalJSONObject implements MarshalerJSONObject 45 | func (s *SourceExt) MarshalJSONObject(enc *gojay.Encoder) { 46 | enc.StringKeyOmitEmpty("omidpn", s.Omidpn) 47 | enc.StringKeyOmitEmpty("omidpv", s.Omidpv) 48 | } 49 | 50 | // IsNil checks if instance is nil 51 | func (s *SourceExt) IsNil() bool { 52 | return s == nil 53 | } 54 | 55 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 56 | func (s *SourceExt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 57 | 58 | switch k { 59 | case "omidpn": 60 | return dec.String(&s.Omidpn) 61 | 62 | case "omidpv": 63 | return dec.String(&s.Omidpv) 64 | 65 | } 66 | return nil 67 | } 68 | 69 | // NKeys returns the number of keys to unmarshal 70 | func (s *SourceExt) NKeys() int { return 0 } 71 | -------------------------------------------------------------------------------- /go/request/rtb_twofive/user.go: -------------------------------------------------------------------------------- 1 | package twofive 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // User object contains information known or derived about the human user of the device (i.e., the 6 | // audience for advertising). The user id is an exchange artifact and may be subject to rotation or other 7 | // privacy policies. However, this user ID must be stable long enough to serve reasonably as the basis for 8 | // frequency capping and retargeting. 9 | type User struct { 10 | Age int `json:"age,omitempty" valid:"optional"` 11 | BuyerUID string `json:"buyeruid,omitempty" valid:"optional"` 12 | YOB int `json:"yob,omitempty" valid:"optional"` 13 | Gender string `json:"gender,omitempty" valid:"in(male|female),optional"` 14 | Keywords string `json:"keywords,omitempty" valid:"optional"` 15 | CustomData string `json:"custom_data,omitempty" valid:"optional"` 16 | Data []Data `json:"data,omitempty" valid:"optional"` 17 | Ext *UserExt `json:"ext" valid:"optional"` 18 | } 19 | 20 | // UserExt Nimbus and IAB extensions 21 | type UserExt struct { 22 | Consent string `json:"consent,omitempty" valid:"-"` // publisher provided GDPR TCF string 23 | UnityBuyerUID string `json:"unity_buyeruid,omitempty" valid:"-"` 24 | FacebookBuyerUID string `json:"facebook_buyeruid,omitempty" valid:"-"` 25 | VungleBuyerUID string `json:"vungle_buyeruid,omitempty" valid:"-"` // buyer id that is generated from the unity sdk and passed to nimbus in the rtb request 26 | MobileFuseData MobileFuseData `json:"mfx_buyerdata,omitempty" valid:"-"` 27 | EIDS EIDS `json:"eids,omitempty" valid:"-"` 28 | } 29 | 30 | // MarshalJSONObject implements MarshalerJSONObject 31 | func (u *User) MarshalJSONObject(enc *gojay.Encoder) { 32 | enc.IntKeyOmitEmpty("age", u.Age) 33 | enc.StringKeyOmitEmpty("buyeruid", u.BuyerUID) 34 | enc.IntKeyOmitEmpty("yob", u.YOB) 35 | enc.StringKeyOmitEmpty("gender", u.Gender) 36 | enc.StringKeyOmitEmpty("keywords", u.Keywords) 37 | enc.StringKeyOmitEmpty("custom_data", u.CustomData) 38 | var dataSlice = Datas(u.Data) 39 | enc.ArrayKeyOmitEmpty("data", dataSlice) 40 | enc.ObjectKeyNullEmpty("ext", u.Ext) 41 | } 42 | 43 | // IsNil checks if instance is nil 44 | func (u *User) IsNil() bool { 45 | return u == nil 46 | } 47 | 48 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 49 | func (u *User) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 50 | 51 | switch k { 52 | case "age": 53 | return dec.Int(&u.Age) 54 | 55 | case "buyeruid": 56 | return dec.String(&u.BuyerUID) 57 | 58 | case "yob": 59 | return dec.Int(&u.YOB) 60 | 61 | case "gender": 62 | return dec.String(&u.Gender) 63 | 64 | case "keywords": 65 | return dec.String(&u.Keywords) 66 | 67 | case "custom_data": 68 | return dec.String(&u.CustomData) 69 | 70 | case "data": 71 | var aSlice = Datas{} 72 | err := dec.Array(&aSlice) 73 | if err == nil && len(aSlice) > 0 { 74 | u.Data = []Data(aSlice) 75 | } 76 | return err 77 | 78 | case "ext": 79 | var userExt UserExt 80 | err := dec.Object(&userExt) 81 | if err == nil { 82 | u.Ext = &userExt 83 | } 84 | return err 85 | 86 | } 87 | return nil 88 | } 89 | 90 | // NKeys returns the number of keys to unmarshal 91 | func (u *User) NKeys() int { return 0 } 92 | 93 | // MarshalJSONObject implements MarshalerJSONObject 94 | func (e *UserExt) MarshalJSONObject(enc *gojay.Encoder) { 95 | enc.StringKeyOmitEmpty("consent", e.Consent) 96 | enc.StringKeyOmitEmpty("unity_buyeruid", e.UnityBuyerUID) 97 | enc.StringKeyOmitEmpty("facebook_buyeruid", e.FacebookBuyerUID) 98 | enc.StringKeyOmitEmpty("vungle_buyeruid", e.VungleBuyerUID) 99 | enc.ObjectKeyOmitEmpty("mfx_buyerdata", &e.MobileFuseData) 100 | enc.ArrayKeyOmitEmpty("eids", e.EIDS) 101 | } 102 | 103 | // IsNil checks if instance is nil 104 | func (e *UserExt) IsNil() bool { 105 | return e == nil 106 | } 107 | 108 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 109 | func (e *UserExt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 110 | 111 | switch k { 112 | 113 | case "consent": 114 | return dec.String(&e.Consent) 115 | 116 | case "unity_buyeruid": 117 | return dec.String(&e.UnityBuyerUID) 118 | 119 | case "facebook_buyeruid": 120 | return dec.String(&e.FacebookBuyerUID) 121 | 122 | case "vungle_buyeruid": 123 | return dec.String(&e.VungleBuyerUID) 124 | 125 | case "mfx_buyerdata": 126 | return dec.Object(&e.MobileFuseData) 127 | 128 | case "eids": 129 | var aSlice = EIDS{} 130 | err := dec.Array(&aSlice) 131 | if err == nil && len(aSlice) > 0 { 132 | e.EIDS = aSlice 133 | } 134 | return err 135 | 136 | } 137 | return nil 138 | } 139 | 140 | // NKeys returns the number of keys to unmarshal 141 | func (e *UserExt) NKeys() int { return 0 } 142 | -------------------------------------------------------------------------------- /go/response/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # response 4 | `import "github.com/adsbynimbus/nimbus-openrtb/go/response"` 5 | 6 | * [Overview](#pkg-overview) 7 | * [Index](#pkg-index) 8 | 9 | ## Overview 10 | 11 | 12 | 13 | ## Index 14 | * [type Bid](#Bid) 15 | * [func (r *Bid) NKeys() int](#Bid.NKeys) 16 | * [func (r *Bid) UnmarshalJSONObject(dec *gojay.Decoder, k string) error](#Bid.UnmarshalJSONObject) 17 | * [type Strings](#Strings) 18 | * [func (a *Strings) UnmarshalJSONArray(dec *gojay.Decoder) error](#Strings.UnmarshalJSONArray) 19 | * [type Trackers](#Trackers) 20 | * [func (t *Trackers) NKeys() int](#Trackers.NKeys) 21 | * [func (t *Trackers) UnmarshalJSONObject(dec *gojay.Decoder, k string) error](#Trackers.UnmarshalJSONObject) 22 | 23 | 24 | #### Package files 25 | [bid_response.go](/src/github.com/adsbynimbus/nimbus-openrtb/go/response/bid_response.go) [primitives.go](/src/github.com/adsbynimbus/nimbus-openrtb/go/response/primitives.go) 26 | 27 | 28 | 29 | 30 | 31 | 32 | ## type [Bid](/src/target/bid_response.go?s=141:736#L6) 33 | ``` go 34 | type Bid struct { 35 | Type string `json:"type"` 36 | AuctionID string `json:"auction_id"` 37 | BidInCents int `json:"bid_in_cents"` 38 | BidRaw float64 `json:"bid_raw"` 39 | ContentType string `json:"content_type"` 40 | Height int `json:"height,omitempty"` 41 | Width int `json:"width,omitempty"` 42 | IsInterstitial int `json:"is_interstitial"` 43 | Markup string `json:"markup"` 44 | Network string `json:"network"` 45 | Trackers *Trackers `json:"trackers,omitempty"` 46 | PlacementID string `json:"placement_id,omitempty"` 47 | } 48 | ``` 49 | Bid represents what Nimbus responds with and is unique to the Nimbus environment 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | ### func (\*Bid) [NKeys](/src/target/bid_response.go?s=1835:1860#L77) 61 | ``` go 62 | func (r *Bid) NKeys() int 63 | ``` 64 | NKeys returns the number of keys to unmarshal 65 | 66 | 67 | 68 | 69 | ### func (\*Bid) [UnmarshalJSONObject](/src/target/bid_response.go?s=983:1052#L27) 70 | ``` go 71 | func (r *Bid) UnmarshalJSONObject(dec *gojay.Decoder, k string) error 72 | ``` 73 | UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 74 | 75 | 76 | 77 | 78 | ## type [Strings](/src/target/primitives.go?s=142:163#L10) 79 | ``` go 80 | type Strings []string 81 | ``` 82 | Strings is an alias of []string 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | ### func (\*Strings) [UnmarshalJSONArray](/src/target/primitives.go?s=226:288#L13) 94 | ``` go 95 | func (a *Strings) UnmarshalJSONArray(dec *gojay.Decoder) error 96 | ``` 97 | UnmarshalJSONArray decodes JSON array elements into slice 98 | 99 | 100 | 101 | 102 | ## type [Trackers](/src/target/bid_response.go?s=825:917#L22) 103 | ``` go 104 | type Trackers struct { 105 | ImpressionTrackers []string `json:"impression_trackers,omitempty"` 106 | } 107 | ``` 108 | Trackers provides a forward thinking impression structure that clients have to fire 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | ### func (\*Trackers) [NKeys](/src/target/bid_response.go?s=2276:2306#L96) 120 | ``` go 121 | func (t *Trackers) NKeys() int 122 | ``` 123 | NKeys returns the number of keys to unmarshal 124 | 125 | 126 | 127 | 128 | ### func (\*Trackers) [UnmarshalJSONObject](/src/target/bid_response.go?s=1939:2013#L80) 129 | ``` go 130 | func (t *Trackers) UnmarshalJSONObject(dec *gojay.Decoder, k string) error 131 | ``` 132 | UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | - - - 142 | Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) 143 | -------------------------------------------------------------------------------- /go/response/bid_response.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import ( 4 | "github.com/francoispqt/gojay" 5 | ) 6 | 7 | // Bid represents what Nimbus responds with and is unique to the Nimbus environment 8 | type Bid struct { 9 | Type string `json:"type"` 10 | AuctionID string `json:"auction_id"` 11 | Adomain []string `json:"adomain,omitempty"` 12 | BidInCents int `json:"bid_in_cents"` 13 | BidRaw float64 `json:"bid_raw"` 14 | ContentType string `json:"content_type"` 15 | Crid string `json:"crid,omitempty"` 16 | Height int `json:"height,omitempty"` 17 | Width int `json:"width,omitempty"` 18 | IsInterstitial int `json:"is_interstitial"` 19 | IsMraid int `json:"is_mraid"` 20 | Markup string `json:"markup"` 21 | Network string `json:"network"` 22 | Trackers *Trackers `json:"trackers,omitempty"` 23 | PlacementID string `json:"placement_id,omitempty"` 24 | Duration int `json:"duration,omitempty"` 25 | Ext *BidExt `json:"ext,omitempty"` 26 | } 27 | 28 | type BidExt struct { 29 | Skadn *Skadn `json:"skadn,omitempty"` 30 | } 31 | 32 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 33 | func (r *Bid) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 34 | 35 | switch k { 36 | case "type": 37 | return dec.String(&r.Type) 38 | 39 | case "auction_id": 40 | return dec.String(&r.AuctionID) 41 | 42 | case "adomain": 43 | var aSlice = Strings{} 44 | err := dec.Array(&aSlice) 45 | if err == nil && len(aSlice) > 0 { 46 | r.Adomain = []string(aSlice) 47 | } 48 | return err 49 | 50 | case "bid_in_cents": 51 | return dec.Int(&r.BidInCents) 52 | 53 | case "bid_raw": 54 | return dec.Float(&r.BidRaw) 55 | 56 | case "content_type": 57 | return dec.String(&r.ContentType) 58 | 59 | case "crid": 60 | return dec.String(&r.Crid) 61 | 62 | case "height": 63 | return dec.Int(&r.Height) 64 | 65 | case "width": 66 | return dec.Int(&r.Width) 67 | 68 | case "is_interstitial": 69 | return dec.Int(&r.IsInterstitial) 70 | 71 | case "is_mraid": 72 | return dec.Int(&r.IsMraid) 73 | 74 | case "markup": 75 | return dec.String(&r.Markup) 76 | 77 | case "network": 78 | return dec.String(&r.Network) 79 | 80 | case "trackers": 81 | var value = &Trackers{} 82 | err := dec.Object(value) 83 | if err == nil { 84 | r.Trackers = value 85 | } 86 | 87 | return err 88 | 89 | case "placement_id": 90 | return dec.String(&r.PlacementID) 91 | 92 | case "duration": 93 | return dec.Int(&r.Duration) 94 | 95 | case "ext": 96 | var value = &BidExt{} 97 | err := dec.Object(value) 98 | if err == nil { 99 | r.Ext = value 100 | } 101 | 102 | return err 103 | 104 | } 105 | return nil 106 | } 107 | 108 | // NKeys returns the number of keys to unmarshal 109 | func (r *Bid) NKeys() int { return 0 } 110 | 111 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 112 | func (e *BidExt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 113 | 114 | switch k { 115 | case "skadn": 116 | var value = &Skadn{} 117 | err := dec.Object(value) 118 | if err == nil { 119 | e.Skadn = value 120 | } 121 | 122 | return err 123 | 124 | } 125 | return nil 126 | } 127 | 128 | // NKeys returns the number of keys to unmarshal 129 | func (e *BidExt) NKeys() int { return 0 } 130 | -------------------------------------------------------------------------------- /go/response/bid_response_test.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/francoispqt/gojay" 8 | 9 | "github.com/google/go-cmp/cmp" 10 | ) 11 | 12 | func TestBidResponseUnmarshaling(t *testing.T) { 13 | tests := []struct { 14 | name string 15 | ResponseJSONString string 16 | }{ 17 | { 18 | name: "json marshal and gojay marshal should output the same way", 19 | ResponseJSONString: `{"adomain":["foo.com","bar.com"],"auction_id":"f6bf21ae-a923-4d7f-9944-af220ff789f6","bid_in_cents":100,"bid_raw":1.00,"content_type":"text/html; charset=utf-8","height":480,"is_interstitial":1,"is_mraid":1,"markup":"...","network":"test_demand","placement_id":"foo_placement","trackers":{"click_trackers":["https://dev.adsbynimbus.com/impression_tracker/bHEyNl8xMHZGU2RUTX6nKs1xDYGt0LspHN22KlZAD2DbeF002MMW2lY2gFkdW8tB91X-2MjKc7valkCGwaYlnJRaP_h6ngrJAI2gDWLJAhhw6bgYrp_-HGGwMvt2wW6eqSXRu4flNA-mZKpldTv6O7Q7QHVh6qwLzXSS5U2Ie0EVRTVixxKY77q8wGA1fRMw_0vnUvpW3Wfm8oJb4bDK4RANmrPKB0t1aZgQ0zxnCsirFb3FwnxM-CMLrXpCOXBOBU9EptcNz2D6C2sMN7EShZt1J-6KP8YLDAJze2HO9lnonh-qc_ZZ3AoHRfz9XnVbWNTwg71uUXYqQ6EsJnPiGZqm7_8JxZCRy8uVh_H7KhpnRu-icu6AJan3CdObcLX453VkGtFIIB8egQ0JJN5Lxxho1jiovynn6xbwqY_BOSMg4pnq9jpGJ7b4zTGnVfLynGXBl1ROTZdvASkBPvaB-lrJNBOPUNLeGUrhLxvv5IHFKXl19Voah7RLn8csMiDl6NyqogjWZM8v4oJWv-jKJJ2a0ZNmE2QtATcm0u5SlnkUpaK6RuGimoe_6SwrNLAJC87NQQGQp5PYQK94Pa4Dq5dVf54gFnaVsuVzak3n9YWrdBFvtaGY5W_t8wqc_f8-E1QvPI1zUTEgh-PDt-MzhbOKN2hPgbMw1Lj8iygd5RLEbtZGHqJ0V-dR467mnAE1CFXuvyrKbB3mxFTgp1a5jHl4-dqilu2XASwqi1BPPadkgeBm_IWCBIGpq3WTZdR7ZDosqqYQpg7WJicWCiBCJR8_F5nToqCLETCqLJlTA0ygz8t7yW3m3fIz5qzhC3GLeCvtqwN_9tW4aVIY1eRUSBb96d8twt9bdcT1x_thMiN3-ZWxSPuUkLqEygcrAZiBEby4Xq9nvvfsVRcTE4bpLVNAaKr35EfQIGVcJIYGyg0I4nC1Wk4VLd2bypAiWsjzqvhPVFsMnIGNMcYIIQqF0-oPd2p3Fq8S8kSY67OvoBlq3dxIV-Em8-QdPaw_gIPeNVR-S5t6SPgFW8L4xuQyGgGMHiRu1PKu1xVEJxhUcFMEE4Sd9SUAWiriKwFFm9d4JH9jQKiMEfxaGhG1t3w1Ipxpp-W_yTkrW7Jrt8qilSruf7fD8_IJ-vTkLhP83-xafFT_87lIPHxU9uy16KslJBEKROF7jRI0LRuIuck6qiNdb96R0C5BUKRPvauoGiXxFbiY15yB9MqSXBHPRK6_8NrPAWYsHpZQhNwOxVDjEpfbX0ghsQwczGTxEcjezVun0viICD4sYWq9vG_25qWw0GuhQKrSEtPCSUFEnTykP2fOwYx8QejRKZ2q-NuYHWUF53e_prcVg5vq3"],"impression_trackers":["https://dev.adsbynimbus.com/impression_tracker/OTVBZ1Fxdy1LclR5PYbemr27sca0vxLUcB4qpILD6LYcBniyWMPDXNCGubAZHxF4j3uNAzYyvU39vgdfYT1KRIyVsm5se-qR15JoJCvEkfFDIl11w7q-0gxAxuAivR8C25v3lJJoyBnbCeA5D0eZBsX36yk4ajHA5D-X9yEeYN6BTqHC-CF571SccCFUAwLs1YVT4Qadgl_ZQtiwA_haP8wyd9U6M-QFULPxnNb824_l-uWzKn5yLpKvliMP_15nL7RYdZMFh8dfzSBDQ1rQ5lX5gQkaDDR3ZZ-cGAg-Sq-z_IBLz-j6-pxXBSvQehL7xKC16dgG5Lzr8mLP0Gualns49T56240OSmikICmNNBpadV_9UtCwmDpcuzCbjS-ANNlr6jHrNzfqmaxHqIAMZ1gr97U3lXDlHqEwDUi9YTsnDpTkmlYarcsA_HGgf22Wm6QhIsh9nGjQCbDJFFIg4BKzGqFrGBDivBJzd0V4nl6wmW_jw_WWF93pnYr4zo_173FWVt8y68dstAxF6NR-2gLbmtl5o7LMUPne8zbkC6fR9XsEeIvmFvcU8i9xdj-K4ly7CT4DVHG_N-IzYYx2-GKLa5bPqISc8OLI7FMPegoMz25bZer3i3UDFs6R5unSHAAnT68iuNmJYyue86j7qmX9TiCwHG_AQkcNQugv5BnJ1vAkvVGwWQZl0AE9cPPJ5hxUDMPMCpXphRUM6gqvDYP8Tr5qJlbs6vJZPymMrIRFHGrqCjkXLilyVLlTSIkp4MF0KykxFcPhRaNUeWkW3jLveUbyn6YlfBGWKEEoPOC0-b4LR-6_7rnM2TWtvgcqTIdPBWb_T3vKJYAZ0VkD-7j4M8KT2o4rU2-oxa3whlFVK6hYuoQj74Ky4dw2WZfrq0yHKgTnaUacyUsELs9ZNiVcGN7QmF4QFv6HxXTkJUVStiDEvLoTBlHCZA_pdnnc0Q0fjY7euhByh-irBA_-EWo4bwsLgFT6PNEhJI28inTGlAeuiW6XBYcj-WSdDLJ-J_dZRY2mzuTvb32c-tZCEsMMXQM-HF-wVxI_KeC8wZrKvMMjqNmVxKEea6-07y-sTna4e4wCwSnTkVy0vCXrFdqcpy7Sj5omiZT4rRjEpnyZ6bOpecuL4L3zIqghDNxuFUUGJI7yn57VkLihUFHVPO0V9U0nD6noyAzG2CDOTrcYQJvXJsSOJibUXjGk1AfzNFTWth3nzk9SKvd0j7DLoky6FL1TThcKMch30r8epx6qlfzPuv54qeSUoxL8EJZsTJzwsvpxNXEzcphCil7MX6TQJq3WjMcZOoSKOw-Iim5gxXl8MmlguHuL0VRVIH3dOv3Ne"]},"type":"static","width":320}`, 20 | }, 21 | } 22 | 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | 26 | var regJSON Bid 27 | err := json.Unmarshal([]byte(tt.ResponseJSONString), ®JSON) 28 | if err != nil { 29 | t.Fatalf("json.Marshal failed %v", err) 30 | } 31 | 32 | var gojayJSON Bid 33 | gojay.UnmarshalJSONObject([]byte(tt.ResponseJSONString), &gojayJSON) 34 | if !cmp.Equal(regJSON, gojayJSON) { 35 | t.Errorf("TestBidRequestMarshalling()\ndiff\n %+v", cmp.Diff(regJSON, gojayJSON)) 36 | } 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /go/response/primitives.go: -------------------------------------------------------------------------------- 1 | // Slice data structures to work with Gojay 2 | 3 | package response 4 | 5 | import ( 6 | "github.com/francoispqt/gojay" 7 | ) 8 | 9 | // Strings is an alias of []string 10 | type Strings []string 11 | 12 | // UnmarshalJSONArray decodes JSON array elements into slice 13 | func (a *Strings) UnmarshalJSONArray(dec *gojay.Decoder) error { 14 | var value string 15 | if err := dec.String(&value); err != nil { 16 | return err 17 | } 18 | *a = append(*a, value) 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /go/response/skadn.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | type Skadn struct { 6 | Version string `json:"version" valid:"optional"` 7 | Network string `json:"network" valid:"optional"` 8 | Campaign string `json:"campaign" valid:"required"` 9 | Itunesitem string `json:"itunesitem" valid:"required"` 10 | Nonce string `json:"nonce" valid:"required"` 11 | Sourceapp string `json:"sourceapp" valid:"required"` 12 | Timestamp string `json:"timestamp" valid:"optional"` 13 | Signature string `json:"signature" valid:"optional"` 14 | } 15 | 16 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 17 | func (s *Skadn) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 18 | 19 | switch k { 20 | case "version": 21 | return dec.String(&s.Version) 22 | 23 | case "network": 24 | return dec.String(&s.Network) 25 | 26 | case "campaign": 27 | return dec.String(&s.Campaign) 28 | 29 | case "itunesitem": 30 | return dec.String(&s.Itunesitem) 31 | 32 | case "nonce": 33 | return dec.String(&s.Nonce) 34 | 35 | case "sourceapp": 36 | return dec.String(&s.Sourceapp) 37 | 38 | case "timestamp": 39 | return dec.String(&s.Timestamp) 40 | 41 | case "signature": 42 | return dec.String(&s.Signature) 43 | 44 | } 45 | return nil 46 | } 47 | 48 | // NKeys returns the number of keys to unmarshal 49 | func (s *Skadn) NKeys() int { return 0 } 50 | -------------------------------------------------------------------------------- /go/response/trackers.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | import "github.com/francoispqt/gojay" 4 | 5 | // Trackers provides a forward-thinking impression structure that clients have to fire typically handled by the nimbus render sdk 6 | type Trackers struct { 7 | ImpressionTrackers []string `json:"impression_trackers,omitempty"` 8 | ClickTrackers []string `json:"click_trackers,omitempty"` 9 | } 10 | 11 | // UnmarshalJSONObject implements gojay's UnmarshalerJSONObject 12 | func (t *Trackers) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { 13 | 14 | switch k { 15 | case "impression_trackers": 16 | var aSlice = Strings{} 17 | err := dec.Array(&aSlice) 18 | if err == nil && len(aSlice) > 0 { 19 | t.ImpressionTrackers = []string(aSlice) 20 | } 21 | return err 22 | 23 | case "click_trackers": 24 | var aSlice = Strings{} 25 | err := dec.Array(&aSlice) 26 | if err == nil && len(aSlice) > 0 { 27 | t.ClickTrackers = []string(aSlice) 28 | } 29 | return err 30 | 31 | } 32 | return nil 33 | } 34 | 35 | // NKeys returns the number of keys to unmarshal 36 | func (t *Trackers) NKeys() int { return 0 } 37 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx6g -Xms6g -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=1 -XX:ReservedCodeCacheSize=320m -XX:+HeapDumpOnOutOfMemoryError 3 | org.gradle.caching=true 4 | org.gradle.configureondemand=true 5 | org.gradle.parallel=true 6 | 7 | # The configuration cache remains disabled due to publishing tasks not working with it 8 | org.gradle.configuration-cache=true 9 | org.gradle.configuration-cache.parallel=true 10 | org.gradle.configuration-cache-problems=warn 11 | org.gradle.configuration-cache.max-problems=5 12 | 13 | group=com.adsbynimbus.openrtb 14 | version=development 15 | 16 | ## Android Build Settings 17 | android.defaults.buildfeatures.resvalues=false 18 | android.defaults.buildfeatures.shaders=false 19 | android.library.defaults.buildfeatures.androidresources=false 20 | android.useAndroidX=true 21 | 22 | ## Kotlin Build Settings 23 | kotlin.code.style=official 24 | kotlin.daemon.jvmargs=-Dfile.encoding=UTF-8 -Xmx6g -Xms6g -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=1 -XX:ReservedCodeCacheSize=320m -XX:+HeapDumpOnOutOfMemoryError 25 | kotlin.incremental.multiplatform=true 26 | kotlin.incremental.native=true 27 | kotlin.native.ignoreDisabledTargets=true 28 | kotlin.stdlib.default.dependency=false 29 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | android = "8.9.2" 3 | dokka = "1.9.20" 4 | kotest = "6.0.0.M3" 5 | kotlin = "2.1.20" 6 | serialization = { require = "[1.5.1, )", prefer = "1.7.3" } 7 | 8 | [plugins] 9 | android = { id = "com.android.library", version.ref = "android" } 10 | dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } 11 | kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } 12 | kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } 13 | kotest = { id = "io.kotest.multiplatform", version.ref = "kotest" } 14 | 15 | [libraries] 16 | kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } 17 | kotest-engine = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" } 18 | kotest-runner = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" } 19 | serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } 20 | 21 | [bundles] 22 | test-android = [ "kotest-runner" ] 23 | test-common = [ "kotest-assertions", "kotest-engine" ] 24 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adsbynimbus/nimbus-openrtb/5136f3be862ddd761daa361dca2cbbaee0642f11/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH= 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /integration-tests/android/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android) 3 | alias(libs.plugins.kotlin) 4 | } 5 | 6 | android { 7 | //noinspection GradleDependency 8 | compileSdk = 34 9 | defaultConfig { 10 | minSdk = 21 11 | multiDexEnabled = true 12 | } 13 | namespace = "com.adsbynimbus.openrtb.android" 14 | 15 | compileOptions { 16 | isCoreLibraryDesugaringEnabled = true 17 | sourceCompatibility = JavaVersion.VERSION_1_8 18 | targetCompatibility = JavaVersion.VERSION_1_8 19 | } 20 | 21 | kotlinOptions { 22 | jvmTarget = "1.8" 23 | } 24 | 25 | sourceSets.configureEach { 26 | if (name.contains("test", ignoreCase = true)) { 27 | java.srcDirs("../../kotlin/src/commonTest/kotlin") 28 | } 29 | } 30 | } 31 | 32 | tasks.withType { 33 | useJUnitPlatform() 34 | } 35 | 36 | dependencies { 37 | implementation(libs.openrtb) 38 | implementation(libs.serialization.json) 39 | implementation(libs.bundles.test) 40 | coreLibraryDesugaring(libs.desguaring) 41 | } 42 | -------------------------------------------------------------------------------- /integration-tests/gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | #noinspection AndroidGradlePluginVersion 3 | android = "7.4.2" 4 | #noinspection NewerVersionAvailable 5 | desugaring = "2.0.3" 6 | #noinspection NewerVersionAvailable 7 | kotest = "5.8.0" 8 | #noinspection NewerVersionAvailable 9 | kotlin = "1.8.22" 10 | #noinspection NewerVersionAvailable 11 | serialization = "1.5.1" 12 | 13 | [plugins] 14 | android = { id = "com.android.library", version.ref = "android" } 15 | kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } 16 | 17 | [libraries] 18 | desguaring = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugaring" } 19 | kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } 20 | kotest-engine = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" } 21 | kotest-runner = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" } 22 | openrtb = { module = "com.adsbynimbus.openrtb:kotlin-android", version = "development" } 23 | serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } 24 | 25 | [bundles] 26 | test = [ 27 | "kotest-assertions", 28 | "kotest-engine", 29 | "kotest-runner", 30 | ] 31 | -------------------------------------------------------------------------------- /integration-tests/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | @file:Suppress("UnstableApiUsage") 2 | 3 | pluginManagement { 4 | repositories { 5 | google { 6 | mavenContent { 7 | includeGroupAndSubgroups("androidx") 8 | includeGroupAndSubgroups("com.android") 9 | includeGroupAndSubgroups("com.google") 10 | } 11 | } 12 | mavenCentral() 13 | gradlePluginPortal() 14 | } 15 | } 16 | 17 | dependencyResolutionManagement { 18 | repositories { 19 | mavenLocal() 20 | google { 21 | mavenContent { 22 | includeGroupAndSubgroups("androidx") 23 | includeGroupAndSubgroups("com.android") 24 | includeGroupAndSubgroups("com.google") 25 | } 26 | } 27 | mavenCentral() 28 | } 29 | } 30 | 31 | rootProject.name = "nimbus-openrtb-integration-tests" 32 | 33 | include("android") 34 | -------------------------------------------------------------------------------- /kotlin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.dokka.gradle.DokkaTask 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | import org.jetbrains.kotlin.gradle.dsl.KotlinVersion 4 | 5 | plugins { 6 | alias(libs.plugins.android) 7 | alias(libs.plugins.kotlin.multiplatform) 8 | alias(libs.plugins.kotest) 9 | alias(libs.plugins.dokka) 10 | alias(libs.plugins.kotlin.serialization) 11 | `maven-publish` 12 | } 13 | 14 | android { 15 | compileSdk = 36 16 | defaultConfig { 17 | minSdk = 21 18 | consumerProguardFile("src/androidMain/consumer-proguard-rules.pro") 19 | } 20 | namespace = "com.adsbynimbus.openrtb" 21 | } 22 | 23 | kotlin { 24 | explicitApi() 25 | 26 | androidTarget { 27 | compilations.configureEach { 28 | compileTaskProvider.configure { 29 | compilerOptions.jvmTarget = JvmTarget.JVM_1_8 30 | } 31 | } 32 | publishLibraryVariants("release") 33 | } 34 | 35 | iosArm64() 36 | iosSimulatorArm64() 37 | 38 | sourceSets { 39 | configureEach { 40 | languageSettings { 41 | apiVersion = KotlinVersion.KOTLIN_1_8.version 42 | languageVersion = KotlinVersion.KOTLIN_1_8.version 43 | optIn("kotlinx.serialization.ExperimentalSerializationApi") 44 | } 45 | } 46 | commonMain.dependencies { 47 | implementation(libs.serialization.json) 48 | } 49 | commonTest.dependencies { 50 | implementation(libs.bundles.test.common) 51 | } 52 | androidUnitTest.dependencies { 53 | implementation(libs.bundles.test.android) 54 | } 55 | } 56 | } 57 | 58 | tasks.withType { 59 | useJUnitPlatform() 60 | } 61 | 62 | tasks.withType().configureEach { 63 | moduleName = "nimbus-openrtb" 64 | 65 | dokkaSourceSets { 66 | named("commonMain") { 67 | sourceLink { 68 | localDirectory = layout.projectDirectory.file("src/$name/kotlin").asFile 69 | remoteUrl = uri("https://github.com/timehop/nimbus-openrtb/kotlin/src/$name/kotlin").toURL() 70 | remoteLineSuffix = "#L" 71 | } 72 | } 73 | } 74 | } 75 | 76 | publishing { 77 | repositories { 78 | maven("s3://adsbynimbus-public/android/sdks") { 79 | name = "aws" 80 | authentication { 81 | create("awsIm") 82 | } 83 | } 84 | providers.environmentVariable("GITHUB_REPOSITORY").orNull?.let { 85 | maven("https://maven.pkg.github.com/$it") { 86 | name = "github" 87 | credentials(PasswordCredentials::class) 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /kotlin/src/androidMain/consumer-proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keepattributes RuntimeVisibleAnnotations,AnnotationDefault 2 | -keepclassmembers class kotlinx.serialization.json.** { 3 | *** Companion; 4 | } 5 | -keepclasseswithmembers class kotlinx.serialization.json.** { 6 | kotlinx.serialization.KSerializer serializer(...); 7 | } 8 | -keepclassmembers @kotlinx.serialization.Serializable class com.adsbynimbus.openrtb.** { 9 | *** Companion; 10 | *** INSTANCE; 11 | kotlinx.serialization.KSerializer serializer(...); 12 | } 13 | 14 | -if @kotlinx.serialization.Serializable class com.adsbynimbus.openrtb.** 15 | -keepclassmembers class com.adsbynimbus.openrtb.<1>$Companion { 16 | kotlinx.serialization.KSerializer serializer(...); 17 | } 18 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/Apis.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * API frameworks supported by the publisher for a creative. 5 | * 6 | * [OpenRTB Section 5.6](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=51) 7 | */ 8 | public object Apis { 9 | 10 | /** Supports VPAID 1 (Unused) **/ 11 | public const val VPAID_1: Byte = 1 12 | 13 | /** Supports VPAID 2 (Unused) **/ 14 | public const val VPAID_2: Byte = 2 15 | 16 | /** Supports MRAID 1 **/ 17 | public const val MRAID_1: Byte = 3 18 | 19 | /** Supports ORMMA */ 20 | public const val ORMMA: Byte = 4 21 | 22 | /** Supports MRAID 2 **/ 23 | public const val MRAID_2: Byte = 5 24 | 25 | /** Supports MRAID 3 **/ 26 | public const val MRAID_3: Byte = 6 27 | 28 | /** Supports OM SDK **/ 29 | public const val OMID: Byte = 7 30 | } 31 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/CompanionTypes.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Companion Ad Type 5 | * 6 | * [OpenRTB Section 5.14](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=54) 7 | */ 8 | public object CompanionTypes { 9 | /** URI to a static resource such as an image */ 10 | public const val STATIC: Byte = 1 11 | 12 | /** HTML to display the companion element */ 13 | public const val HTML: Byte = 2 14 | 15 | /** URI source for an IFrame to display the companion element */ 16 | public const val IFRAME: Byte = 3 17 | } 18 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/ConnectionType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Options for the type of device connectivity 5 | * 6 | * [OpenRTB Section 5.22](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=56) 7 | */ 8 | public object ConnectionType { 9 | public const val UNKNOWN: Byte = 0 10 | public const val ETHERNET: Byte = 1 11 | public const val WIFI: Byte = 2 12 | public const val CELLULAR_UNKNOWN: Byte = 3 13 | public const val CELLULAR_2G: Byte = 4 14 | public const val CELLULAR_3G: Byte = 5 15 | public const val CELLULAR_4G: Byte = 6 16 | } 17 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/CreativeAttributes.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Standard list of creative attributes. 5 | * 6 | * Can describe an ad being served or serve as restrictions of thereof. 7 | * 8 | * [OpenRTB Section 5.3](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=50) 9 | */ 10 | public object CreativeAttributes { 11 | 12 | /** Audio Ad (Auto-Play) */ 13 | public const val AUDIO_AD_AUTO_PLAY: Byte = 1 14 | 15 | /** Audio Ad (User Initiated) */ 16 | public const val AUDIO_AD_USER_INITIATED: Byte = 2 17 | 18 | /** Expandable (Automatic) */ 19 | public const val EXPANDABLE_AUTOMATIC: Byte = 3 20 | 21 | /** Expandable (User Initiated - Click) */ 22 | public const val EXPANDABLE_USER_CLICK: Byte = 4 23 | 24 | /** Expandable (User Initiated - Rollover) */ 25 | public const val EXPANDABLE_USER_ROLLOVER: Byte = 5 26 | 27 | /** In-Banner Video Ad (Auto-Play) */ 28 | public const val BANNER_VIDEO_AUTO_PLAY: Byte = 6 29 | 30 | /** In-Banner Video Ad (User Initiated) */ 31 | public const val BANNER_VIDEO_USER_INITIATED: Byte = 7 32 | 33 | /** Pop (e.g., Over, Under, or Upon Exit) */ 34 | public const val HAS_POPUP: Byte = 8 35 | 36 | /** Provocative or Suggestive Imagery */ 37 | public const val PROVOCATIVE_OR_SUGGESTIVE: Byte = 9 38 | 39 | /** Shaky, Flashing, Flickering, Extreme Animation, Smileys */ 40 | public const val EXTREME_ANIMATION: Byte = 10 41 | 42 | /** Surveys */ 43 | public const val SURVEYS: Byte = 11 44 | 45 | /** Text Only */ 46 | public const val TEXT_ONLY: Byte = 12 47 | 48 | /** User Byteeractive (e.g., Embedded Games) */ 49 | public const val USER_INTERACTIVE_AND_GAMES: Byte = 13 50 | 51 | /** Windows Dialog or Alert Style */ 52 | public const val DIALOG_OR_ALERT_STYLE: Byte = 14 53 | 54 | /** Has Audio On/Off Button */ 55 | public const val HAS_VOLUME_TOGGLE: Byte = 15 56 | 57 | /** Ad Provides Skip Button (e.g. VPAID-rendered skip button on pre-roll video) */ 58 | public const val HAS_SKIP_BUTTON: Byte = 16 59 | 60 | /** Adobe Flash */ 61 | public const val ADOBE_FLASH: Byte = 17 62 | } 63 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/DataType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | public object DataType { 4 | public const val SPONSORED: Byte = 1 5 | public const val DESC: Byte = 2 6 | public const val RATING: Byte = 3 7 | public const val LIKES: Byte = 4 8 | public const val DOWNLOADS: Byte = 5 9 | public const val PRICE: Byte = 6 10 | public const val SALEPRICE: Byte = 7 11 | public const val PHONE: Byte = 8 12 | public const val ADDRESS: Byte = 9 13 | public const val DESC2: Byte = 10 14 | public const val DISPLAYURL: Byte = 11 15 | public const val CTATEXT: Byte = 12 16 | } 17 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/DeliveryMethods.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Content Delivery Method 5 | * 6 | * [OpenRTB Section 5.15](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=54) 7 | */ 8 | public object DeliveryMethods { 9 | /** Streaming Media */ 10 | public const val STREAMING: Byte = 1 11 | 12 | /** Progressive Media */ 13 | public const val PROGRESSIVE: Byte = 2 14 | 15 | /** Downloaded Media */ 16 | public const val DOWNLOAD: Byte = 3 17 | } 18 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/DeviceType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Type of device from which the impression originated. 5 | * 6 | * [OpenRTB Section 5.21](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=56) 7 | */ 8 | public object DeviceType { 9 | /** Interchangeable with Phone and Tablet */ 10 | public const val MOBILE_TABLET: Byte = 1 11 | public const val PERSONAL_COMPUTER: Byte = 2 12 | public const val CONNECTED_TV: Byte = 3 13 | 14 | /** Interchangeable with MobileTablet */ 15 | public const val PHONE: Byte = 4 16 | 17 | /** Interchangeable with MobileTablet */ 18 | public const val TABLET: Byte = 5 19 | public const val CONNECTED_DEVICE: Byte = 6 20 | public const val SET_TOP_BOX: Byte = 7 21 | } 22 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/ImageType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | public object ImageType { 4 | public const val ICON: Byte = 1 5 | 6 | public const val MAIN: Byte = 3 7 | } 8 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/Linearity.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Linearity 5 | * 6 | * [OpenRTB Section 5.7](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=52) 7 | */ 8 | public object Linearity { 9 | /** Linear / In-Stream Video */ 10 | public const val LINEAR: Byte = 1 11 | 12 | /** Non-Linear / Overlay Video*/ 13 | public const val NON_LINEAR: Byte = 2 14 | } 15 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/LocationType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** Indicates how the geographic information was determined. */ 4 | public object LocationType { 5 | public const val GPS: Byte = 1 6 | public const val IP_LOOKUP: Byte = 2 7 | public const val USER_PROVIDED: Byte = 3 8 | } 9 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/NativeAdContext.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | public object NativeAdContext { 4 | public const val CONTENT: Byte = 1 // Content-centric context such as newsfeed, article, image gallery, video gallery, or similar. 5 | public const val SOCIAL: Byte = 2 // Social-centric context such as social network feed, email, chat, or similar. 6 | public const val PRODUCT: Byte = 3 // Product context such as product listings, details, recommendations, reviews, or similar. 7 | } 8 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/NativeAdContextSubType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | public object NativeAdContextSubType { 4 | public val GENERALORMIXED: Byte = 10 // General or mixed content 5 | public val ARTICLE: Byte = 11 // Primarily article content (which of course could include images, etc as part of the article) 6 | public val VIDEO: Byte = 12// Primarily video content 7 | public val AUDIO: Byte = 13 // Primarily audio content 8 | public val IMAGE: Byte = 14 // Primarily image content 9 | public val USERGENERATED: Byte = 15 // User-generated content - forums, comments, etc 10 | public val SOCIAL: Byte = 20 // General social content such as a general social network 11 | public val EMAIL: Byte = 21 // Primarily email content 12 | public val CHAT: Byte = 22 // Primarily chat/IM content 13 | public val SALES: Byte = 30 // Content focused on selling products, whether digital or physical 14 | public val APPSTORE: Byte = 31 // Application store/marketplace 15 | public val PRODUCTREVIEWS: Byte = 32 // Product reviews site primarily (which may sell product secondarily) 16 | } 17 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/PlacementType.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | import com.adsbynimbus.openrtb.request.Impression 4 | 5 | /** 6 | * Video Placement Type 7 | * 8 | * [OpenRTB Section 5.9](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=52) 9 | */ 10 | public object PlacementType { 11 | /** 12 | * Played before, during, or after the streaming video content that the consumer has 13 | * requested (e.g., Pre-roll, Mid-roll, Post-roll). 14 | */ 15 | public const val IN_STREAM: Byte = 1 16 | 17 | /** 18 | * Exists within a web banner that leverages the banner space to deliver a video experience 19 | * as opposed to another static or rich media format. The format relies on the existence of 20 | * display ad inventory on the page for its delivery. 21 | */ 22 | public const val IN_BANNER: Byte = 2 23 | 24 | /** 25 | * Loads and plays dynamically between paragraphs of editorial content; existing as a 26 | * standalone branded message. 27 | */ 28 | public const val IN_ARTICLE: Byte = 3 29 | 30 | /** Found in content, social, or product feeds. */ 31 | public const val IN_FEED: Byte = 4 32 | 33 | /** 34 | * Covers the entire or a portion of screen area, but is always on screen while displayed 35 | * (i.e. cannot be scrolled out of view). 36 | * 37 | * Note that a full-screen interstitial (e.g., in mobile) can be distinguished from a 38 | * floating/slider unit by the [Impression.instl] field. 39 | */ 40 | public const val INTERSTITIAL_SLIDER_FLOATING: Byte = 5 41 | } 42 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/PlaybackMethods.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Media Playback Method 5 | * 6 | * [OpenRTB Section 5.10](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=53) 7 | */ 8 | public object PlaybackMethods { 9 | /** Playback initiates on Page Load with Sound On */ 10 | public const val PAGE_LOAD_SOUND_ON: Byte = 1 11 | 12 | /** Playback initiates on Page Load with Sound Off by Default */ 13 | public const val PAGE_LOAD_SOUND_OFF: Byte = 2 14 | 15 | /** Playback initiates on Click with Sound On */ 16 | public const val CLICK_SOUND_ON: Byte = 3 17 | 18 | /** Playback initiates on Mouse-Over with Sound On */ 19 | public const val MOUSE_OVER_SOUND_ON: Byte = 4 20 | 21 | /** Playback initiates on Entering Viewport with Sound On */ 22 | public const val ENTER_VIEWPORT_SOUND_ON: Byte = 5 23 | 24 | /** Playback initiates on Entering Viewport with Sound Off by default */ 25 | public const val ENTER_VIEWPORT_SOUND_OFF: Byte = 6 26 | } 27 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/Position.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Describes the position of the ad as a relative measure of visibility or prominence. 5 | * 6 | * This OpenRTB table has values derived from the Inventory Quality Guidelines (IQG). 7 | * Values 4 - 7 apply to apps. 8 | * 9 | * [OpenRTB Section 5.4](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=51) 10 | */ 11 | public object Position { 12 | public const val UNKNOWN: Byte = 0 13 | public const val ABOVE_THE_FOLD: Byte = 1 14 | public const val BELOW_THE_FOLD: Byte = 3 15 | public const val HEADER: Byte = 4 16 | public const val FOOTER: Byte = 5 17 | public const val SIDEBAR: Byte = 6 18 | public const val FULLSCREEN: Byte = 7 19 | } 20 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/Protocols.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | /** 4 | * Protocols 5 | * 6 | * [OpenRTB Section 5.8](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=52) 7 | */ 8 | public object Protocols { 9 | /** Vast 2.0 */ 10 | public const val VAST_2: Byte = 2 11 | 12 | /** Vast 3.0 */ 13 | public const val VAST_3: Byte = 3 14 | 15 | /** Vast 2.0 Wrapper */ 16 | public const val VAST_2_WRAPPER: Byte = 5 17 | 18 | /** Vast 3.0 Wrapper */ 19 | public const val VAST_3_WRAPPER: Byte = 6 20 | 21 | /** Vast 4.0 */ 22 | public const val VAST_4: Byte = 7 23 | 24 | /** Vast 4.0 Wrapper */ 25 | public const val VAST_4_WRAPPER: Byte = 8 26 | } 27 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/enumerations/TitleLength.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.enumerations 2 | 3 | public object TitleLength { 4 | public const val SHORT: Int = 25 5 | 6 | public const val MEDIUM: Int = 90 7 | 8 | public const val LONG: Int = 140 9 | } 10 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/App.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object should be included if the ad supported content is a non-browser application 9 | * (typically in mobile) as opposed to a website. A bid request must not contain both an App and a 10 | * Site object. At a minimum, it is useful to provide an App ID or bundle, but this is not strictly 11 | * required. 12 | * 13 | * [OpenRTB Section 3.2.14](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=25) 14 | * 15 | * @property name App name (may be aliased at the publisher’s request). 16 | * @property bundle A platform-specific application identifier intended to be unique to the app and 17 | * independent of the exchange. On Android, this should be a bundle or package name 18 | * (e.g., com.foo.mygame). On iOS, it is typically a numeric ID. 19 | * @property domain Domain of the app (e.g., "adsbynimbus.com"). 20 | * @property storeurl App store URL for an installed app; for IQG 2.1 compliance. 21 | * @property ver Application version. 22 | * @property keywords A list of keywords describing the app. 23 | * @property cat Array of IAB content categories of the app. 24 | * @property sectioncat Array of IAB content categories that describe the current section of the 25 | * app. 26 | * @property pagecat Array of IAB content categories that describe the current page or view of the 27 | * app. 28 | * @property privacypolicy Indicates if the app has a privacy policy. (0 = No, 1 = Yes) 29 | * @property paid Indicates if the app is free or paid. (0 = Free, 1 = Paid) 30 | * @property publisher Details about the publisher of the app. 31 | */ 32 | @Serializable 33 | public class App( 34 | @JvmField @SerialName("name") public var name: String? = null, 35 | @JvmField @SerialName("bundle") public var bundle: String? = null, 36 | @JvmField @SerialName("domain") public var domain: String? = null, 37 | @JvmField @SerialName("storeurl") public var storeurl: String? = null, 38 | @JvmField @SerialName("ver") public var ver: String? = null, 39 | @JvmField @SerialName("keywords") public var keywords: String? = null, 40 | @JvmField @SerialName("cat") public var cat: Array? = null, 41 | @JvmField @SerialName("sectioncat") public var sectioncat: Array? = null, 42 | @JvmField @SerialName("pagecat") public var pagecat: Array? = null, 43 | @JvmField @SerialName("privacypolicy") public var privacypolicy: Byte? = null, 44 | @JvmField @SerialName("paid") public var paid: Byte? = null, 45 | @JvmField @SerialName("publisher") public var publisher: Publisher? = null, 46 | ) 47 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Asset.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object represents a native asset object, which is the main container 9 | * for each asset requested or supported by Exchange on behalf of the rendering client. 10 | * 11 | * [OpenRTB Native Ads 1.2](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf) 12 | */ 13 | @Serializable 14 | public class Asset ( 15 | @JvmField @SerialName("id") public var id: Int, 16 | @JvmField @SerialName("required") public var required: Byte, 17 | @JvmField @SerialName("ext") public var ext: Map? = null, 18 | @JvmField @SerialName("title") public var title: TitleObject? = null, 19 | @JvmField @SerialName("img") public var img: ImageObject? = null, 20 | @JvmField @SerialName("video") public var video: VideoObject? = null, 21 | @JvmField @SerialName("data") public var data: DataObject? = null, 22 | ){ 23 | @Serializable 24 | public class TitleObject( 25 | @JvmField @SerialName("len") public var length: Int 26 | ) 27 | @Serializable 28 | public class ImageObject( 29 | @JvmField @SerialName("type") public var type: Byte, 30 | @JvmField @SerialName("w") public var w: Int? = null, 31 | @JvmField @SerialName("h") public var h: Int? = null, 32 | @JvmField @SerialName("hmin") public var hmin: Int? = null, 33 | @JvmField @SerialName("wmin") public var wmin: Int? = null, 34 | ) 35 | @Serializable 36 | public class VideoObject( 37 | @JvmField @SerialName("mimes") public var mimes: Array? = null, 38 | @JvmField @SerialName("minduration") public var minduration: Int = 0, 39 | @JvmField @SerialName("maxduration") public var maxduration: Int = 60, 40 | @JvmField @SerialName("protocols") public var protocols: ByteArray? = null, 41 | ) 42 | @Serializable 43 | public class DataObject( 44 | @JvmField @SerialName("type") public var type: Byte, 45 | @JvmField @SerialName("len") public var len: Int, 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Banner.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object represents the most general type of impression. 9 | * 10 | * Although the term "banner" may have very specific meaning in other contexts, here it can be many 11 | * things including a simple static image, an expandable ad unit, or even in-banner video (refer to 12 | * [Video] for generalized and full featured video ad units). An array of [Banner] objects can also 13 | * appear within the [Video] to describe optional companion ads defined in the VAST specification. 14 | * The presence of a [Banner] as a subordinate of the [Impression] object indicates that this 15 | * impression is offered as a banner type impression. At the publisher’s discretion, that same 16 | * impression may also be offered as video, audio, and/or native by also including as [Impression] 17 | * subordinates objects of those types. However, any given bid for the impression must conform to 18 | * one of the offered types. 19 | * 20 | * [OpenRTB Section 3.2.6](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=19) 21 | * 22 | * @property bidfloor Minimum bid for this banner impression expressed in CPM. 23 | * @property battr Set of creative attributes to block. 24 | * @property format Array of Format objects representing the banner sizes permitted. 25 | * @property w Exact width in device independent pixels (DIPS). 26 | * @property h Exact height in device independent pixels (DIPS). 27 | * @property pos Ad position on screen. 28 | * @property api Set of supported Api frameworks for this banner impression. If an Api is not 29 | * explicitly listed, it is assumed not to be supported. 30 | * @property vcm The type of companion ad if used in a Video object. (0 - Concurrent, 1 - End Card) 31 | */ 32 | @Serializable 33 | public class Banner( 34 | @JvmField @SerialName("w") public var w: Int, 35 | @JvmField @SerialName("h") public var h: Int, 36 | @JvmField @SerialName("format") public var format: Array? = null, 37 | @JvmField @SerialName("bidfloor") public var bidfloor: Float = 0f, 38 | @JvmField @SerialName("battr") public var battr: ByteArray? = null, 39 | @JvmField @SerialName("pos") public var pos: Byte = 0, 40 | @JvmField @SerialName("api") public var api: ByteArray? = null, 41 | @JvmField @SerialName("vcm") public var vcm: Byte? = null, 42 | ) 43 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/BidRequest.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.json.Json 6 | import kotlin.jvm.JvmField 7 | import kotlin.jvm.JvmOverloads 8 | import kotlin.jvm.JvmStatic 9 | 10 | /** 11 | * The top-level bid request object contains a globally unique bid request or auction ID. 12 | * 13 | * This id attribute is required as is at least one impression object (Section 3.2.4). Other 14 | * attributes in this top-level object establish rules and restrictions that apply to all 15 | * impressions being offered. There are also several subordinate objects that provide detailed data 16 | * to potential buyers. Among these are the Site and App objects, which describe the type of 17 | * published media in which the impression(s) appear. These objects are highly recommended, but only 18 | * one applies to a given bid request depending on whether the media is browser-based web content or 19 | * a non-browser application, respectively. 20 | * 21 | * [OpenRTB Section 3.2.1](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=15) 22 | * 23 | * @property imp Array of impression objects representing the impressions offered. 24 | * Only 1 impression object is supported. 25 | * @property app Details about the publisher’s app (i.e., non-browser applications). 26 | * @property device Details about the user’s device to which the impression will be delivered. 27 | * @property format A format object representing the width and height of the device. 28 | * This is not part of the spec, adding this here for convenience allows height and 29 | * width to be passed without the video/banner object to backwards support the GET 30 | * @property user Details about the human user of the device; the advertising audience. 31 | * @property test Indicator of test mode in which auctions are not billable (0: live, 1: test) 32 | * @property tmax Maximum time in milliseconds the exchange allows for bids to be received including 33 | * Internet latency to avoid timeout. 34 | * This value supersedes any a priori guidance from the exchange. If this value is 35 | * omitted Nimbus will default to 500. 36 | * @property badv Block list of advertisers by their domains (e.g., "ford.com"). 37 | * @property source A Source object that provides data about the inventory source and which entity 38 | * makes the final decision. 39 | * @property regs A Regs object that specifies any industry, legal, or governmental regulations in 40 | * force for this request. 41 | * @property customSignals Custom signals for this request 42 | * @property ext Placeholder for exchange-specific extensions to OpenRTB. 43 | */ 44 | @Serializable 45 | public class BidRequest( 46 | @JvmField @SerialName("imp") public var imp: Array = emptyArray(), 47 | @JvmField @SerialName("app") public var app: App? = null, 48 | @JvmField @SerialName("device") public var device: Device? = null, 49 | @JvmField @SerialName("format") public var format: Format = Format(0, 0), 50 | @JvmField @SerialName("user") public var user: User? = null, 51 | @JvmField @SerialName("test") public var test: Byte = 0, 52 | @JvmField @SerialName("tmax") public var tmax: Int = 500, 53 | @JvmField @SerialName("badv") public var badv: Array? = null, 54 | @JvmField @SerialName("source") public var source: Source? = null, 55 | @JvmField @SerialName("regs") public var regs: Regs? = null, 56 | @JvmField @SerialName("custom_signals") public var customSignals: Signals? = null, 57 | @JvmField @SerialName("ext") public val ext: MutableMap = mutableMapOf(), 58 | ) { 59 | 60 | /** 61 | * Any unique string value to identify the session. 62 | * 63 | * Defaults to a random UUID when using the Nimbus SDK 64 | */ 65 | public inline var session_id: String 66 | get() = ext["session_id"] ?: "" 67 | set(value) { ext["session_id"] = value } 68 | 69 | public companion object { 70 | /** Required header for all requests to Nimbus defining the OpenRTB version */ 71 | public const val OPENRTB_HEADER: String = "x-openrtb-version" 72 | 73 | /** The current supported OpenRTB version by this request object */ 74 | public const val OPENRTB_VERSION: String = "2.5" 75 | 76 | @JvmField 77 | public val lenientSerializer: Json = Json { 78 | coerceInputValues = true 79 | explicitNulls = false 80 | ignoreUnknownKeys = true 81 | } 82 | 83 | /** Encodes a BidRequest to a Json string using the built in serializer */ 84 | @JvmStatic @JvmOverloads 85 | public fun BidRequest.toJson(jsonSerializer: Json = lenientSerializer): String = 86 | jsonSerializer.encodeToString(serializer(), this) 87 | 88 | /** Decodes a BidRequest from a Json string using the built in serializer */ 89 | @JvmStatic @JvmOverloads 90 | public fun fromJson(json: String, jsonSerializer: Json = lenientSerializer): BidRequest = 91 | jsonSerializer.decodeFromString(serializer(), json) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Data.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("RedundantVisibilityModifier") 2 | 3 | package com.adsbynimbus.openrtb.request 4 | 5 | import kotlinx.serialization.SerialName 6 | import kotlinx.serialization.Serializable 7 | import kotlin.jvm.JvmField 8 | 9 | /** 10 | * The data and segment objects together allow additional data about the related object (e.g., user, 11 | * content) to be specified. This data may be from multiple sources whether from the exchange itself 12 | * or third parties as specified by the id field. A bid request can mix data objects from multiple 13 | * providers. The specific data providers in use should be published by the exchange a priori to its bidders. 14 | * 15 | * [OpenRTB Section 3.2.21](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=31) 16 | * 17 | * @property id Exchange-specific ID for the data provider. 18 | * @property name Exchange-specific name for the data provider. 19 | * @property segment Array of [Segment] objects that contain the actual data values. 20 | * @see [OpenRTB Section 3.2.22](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=31) 21 | */ 22 | @Serializable 23 | public class Data( 24 | @JvmField @SerialName("id") public var id: String? = null, 25 | @JvmField @SerialName("name") public var name: String? = null, 26 | @JvmField @SerialName("segment") public var segment: Set? = null, 27 | ) 28 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Device.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object provides information pertaining to the device through which the user is interacting. 9 | * 10 | * Device information includes its hardware, platform, location, and carrier data. The device can 11 | * refer to a mobile handset, a desktop computer, set top box, or other digital device. 12 | * 13 | * [OpenRTB Section 3.2.18](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=28) 14 | * 15 | * @property ua Browser user agent string. 16 | * @property geo Location of the device assumed to be the user’s current location defined by a Geo 17 | * object. 18 | * @property dnt Standard "Do Not Track" flag as set in the header by the browser. 19 | * (0 = tracking is unrestricted; 1 = do not track) 20 | * @property lmt "Limit Ad Tracking" signal commercially endorsed (e.g., iOS, Android). 21 | * 0 = tracking is unrestricted 22 | * 1 = tracking must be limited per commercial guidelines 23 | * @property ip IPv4 address closest to device. Will be set automatically by Nimbus. 24 | * @property devicetype The general type of device. 25 | * @property make Device make (e.g., "Google"). 26 | * @property model Device model (e.g., "Pixel"). 27 | * @property hwv Device hardware version 28 | * @property os Device operating system (e.g., "Android") 29 | * @property osv Device operating system version (e.g., "10", "9", "8.1", "8"). 30 | * @property h Physical height of the screen in pixels. 31 | * @property w Physical width of the screen in pixels. 32 | * @property pxratio The ratio of physical pixels to device independent pixels. 33 | * @property language Browser language using ISO-639-1-alpha-2 34 | * @property carrier Carrier or ISP (e.g., "Verizon") using exchange curated string names which 35 | * should be published to bidders a priori. 36 | * @property connectiontype Network connection type. 37 | * @property ifa ID sanctioned for advertiser use in the clear (i.e., not hashed). 38 | */ 39 | @Serializable 40 | public class Device( 41 | @JvmField @SerialName("ua") public var ua: String, 42 | @JvmField @SerialName("ifa") public var ifa: String, 43 | @JvmField @SerialName("make") public val make: String, 44 | @JvmField @SerialName("model") public val model: String, 45 | @JvmField @SerialName("hwv") public var hwv: String? = null, 46 | @JvmField @SerialName("os") public val os: String, 47 | @JvmField @SerialName("osv") public val osv: String, 48 | @JvmField @SerialName("h") public var h: Int, 49 | @JvmField @SerialName("w") public var w: Int, 50 | @JvmField @SerialName("pxratio") public var pxratio: Float? = null, 51 | @JvmField @SerialName("language") public var language: String? = null, 52 | @JvmField @SerialName("devicetype") public val devicetype: Byte = 0, 53 | @JvmField @SerialName("connectiontype") public var connectiontype: Byte = 0, 54 | @JvmField @SerialName("dnt") public var dnt: Byte = 0, 55 | @JvmField @SerialName("lmt") public var lmt: Byte = 0, 56 | @JvmField @SerialName("geo") public var geo: Geo? = null, 57 | @JvmField @SerialName("ip") public var ip: String? = null, 58 | @JvmField @SerialName("carrier") public var carrier: String? = null, 59 | ) 60 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Format.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object represents an allowed size (i.e., height and width combination) 9 | * 10 | * [OpenRTB Section 3.2.10](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=23) 11 | * 12 | * @property w width in device independent pixels (DIPS). 13 | * @property h height in device independent pixels (DIPS). 14 | */ 15 | @Serializable 16 | public class Format( 17 | @JvmField @SerialName("w") public val w: Int, 18 | @JvmField @SerialName("h") public val h: Int, 19 | ) { 20 | public companion object { 21 | /** 320 by 480 portrait interstitial */ 22 | @JvmField public val INTERSTITIAL_PORT: Format = Format(320, 480) 23 | /** 480 by 320 landscape interstitial */ 24 | @JvmField public val INTERSTITIAL_LAND: Format = Format(480, 320) 25 | /** 320 by 50 mobile banner */ 26 | @JvmField public val BANNER_320_50: Format = Format(320, 50) 27 | /** 300 by 250 medium rectangle */ 28 | @JvmField public val BANNER_300_250: Format = Format(300, 250) 29 | /** An alias for a 300 by 250 medium rectangle */ 30 | @JvmField public val LETTERBOX: Format = BANNER_300_250 31 | /** 300 by 600 half page */ 32 | @JvmField public val HALF_SCREEN: Format = Format(300, 600) 33 | /** 728 by 90 mobile banner */ 34 | @JvmField public val LEADERBOARD: Format = Format(728, 90) 35 | /** 300 by 250 medium rectangle */ 36 | public inline val MREC: Format get() = BANNER_300_250 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Geo.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object encapsulates various methods for specifying a geographic location. 9 | * 10 | * When subordinate to a Device object, it indicates the location of the device which can also be 11 | * interpreted as the user’s current location. When subordinate to a User object, it indicates the 12 | * location of the user’s home base (i.e., not necessarily their current location). 13 | * 14 | * The lat/lon attributes should only be passed if they conform to the accuracy depicted in the type 15 | * attribute. For example, the centroid of a geographic region such as postal code should not be 16 | * passed. 17 | * 18 | * [OpenRTB Section 3.2.19](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=29) 19 | * 20 | * @property lat Latitude from -90.0 to +90.0, where negative is south. 21 | * @property lon Longitude from -180.0 to +180.0, where negative is west 22 | * @property type Source of location data; recommended when passing lat/lon. 23 | * @property accuracy Estimated location accuracy in meters. 24 | * Recommended when lat/lon are specified and derived from a device’s location 25 | * services (i.e., type = 1). Note that this is the accuracy as reported from the 26 | * device. Consult OS specific documentation (e.g., Android, iOS) for exact 27 | * interpretation. 28 | * @property country Country code using ISO-3166-1-alpha-3. 29 | * @property city City using United Nations Code for Trade & Transport Locations. 30 | * @property metro Google metro code; similar to but not exactly Nielsen DMAs. 31 | * @property state 2-letter state code. 32 | * @see [United Nations Location Codes](http://www.unece.org/cefact/locode/service/location.htm) 33 | * @see [Google Metro codes](code.google.com/apis/adwords/docs/appendix/metrocodes.html) 34 | */ 35 | @Serializable 36 | public class Geo( 37 | @JvmField @SerialName("lat") public var lat: Float? = null, 38 | @JvmField @SerialName("lon") public var lon: Float? = null, 39 | @JvmField @SerialName("type") public var type: Byte? = null, 40 | @JvmField @SerialName("accuracy") public var accuracy: Int? = null, 41 | @JvmField @SerialName("country") public var country: String? = null, 42 | @JvmField @SerialName("city") public var city: String? = null, 43 | @JvmField @SerialName("metro") public var metro: String? = null, 44 | @JvmField @SerialName("state") public var state: String? = null, 45 | ) 46 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Impression.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object describes an ad placement or impression being auctioned. 9 | * 10 | * A single [BidRequest] can include multiple Impression objects, a use case for which might be an 11 | * exchange that supports selling all ad positions on a given page. Each [Impression] object has a 12 | * required ID so that bids can reference them individually. The presence of [Banner], [Video], or 13 | * [Native], subordinate to the Imp object indicates the type of impression being offered. The 14 | * publisher can choose one such type which is the typical case or mix them at their discretion. 15 | * However, any given bid for the impression must conform to one of the offered types. 16 | * 17 | * [OpenRTB Section 3.2.4](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=12) 18 | * 19 | * @property banner A banner object; required if this impression is offered as a banner ad 20 | * opportunity or is used in the Nimbus hybrid auction. 21 | * @property video A video object; required if this impression is offered as a video ad opportunity 22 | * or is used in Nimbus hybrid auction. 23 | * @property native A native object; required if this impression is offered as a native ad 24 | * opportunity or is used in a Nimbus hybrid auction. 25 | * @property instl An integer flag marking this impression object as an interstitial. 26 | * 1 = the ad is interstitial or full screen, 27 | * 0 = not interstitial. 28 | * @property secure Flag to indicate if the impression requires secure HTTPS URL creative assets and 29 | * markup. 30 | * 0 = non-secure 31 | * 1 = secure 32 | * @property ext Placeholder for exchange-specific extensions to OpenRTB 33 | */ 34 | @Serializable 35 | public class Impression( 36 | @JvmField @SerialName("banner") public var banner: Banner? = null, 37 | @JvmField @SerialName("video") public var video: Video? = null, 38 | @JvmField @SerialName("native") public var native: Native? = null, 39 | @JvmField @SerialName("instl") public var instl: Byte = 0, 40 | @JvmField @SerialName("secure") public var secure: Byte = 1, 41 | @JvmField @SerialName("ext") public var ext: Extension, 42 | ) { 43 | /** 44 | * Impression extension unique to Nimbus 45 | * 46 | * @property position Required string identifying the name of the placement that will be 47 | * displayed on the Nimbus dashboard. 48 | * @property aps The list of key value pairs provided by a DTBRequest from the APS library. 49 | * @property facebook_app_id The identifier for this app provided by Facebook. Required if 50 | * including Facebook demand in this request. 51 | * @property facebook_test_ad_type An optional ad type to force a test response for validating 52 | * integrations. 53 | * @see [Facebook Testing](https://developers.facebook.com/docs/audience-network/overview/in-house-mediation/server-to-server/testing) 54 | */ 55 | @Serializable 56 | public class Extension( 57 | @JvmField @SerialName("position") public var position: String, 58 | @JvmField @SerialName("aps") public var aps: Set>> = emptySet(), 59 | @JvmField @SerialName("facebook_app_id") public var facebook_app_id: String? = null, 60 | @JvmField @SerialName("facebook_test_ad_type") public var facebook_test_ad_type: String? = null, 61 | ) 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Native.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import com.adsbynimbus.openrtb.enumerations.NativeAdContext 4 | import com.adsbynimbus.openrtb.enumerations.NativeAdContextSubType 5 | import com.adsbynimbus.openrtb.enumerations.PlacementType 6 | import kotlinx.serialization.SerialName 7 | import kotlinx.serialization.Serializable 8 | import kotlin.jvm.JvmField 9 | 10 | /** 11 | * This public class represents a native type impression. 12 | * 13 | * Native ad units are intended to blend seamlessly into the surrounding content (e.g., a sponsored 14 | * Twitter or Facebook post). As such, the response must be well-structured to afford the publisher 15 | * fine-grained control over rendering. The Native Subcommittee has developed a companion 16 | * specification to OpenRTB called the Dynamic Native Ads API. It defines the request parameters and 17 | * response markup structure of native ad units. This object provides the means of transporting 18 | * request parameters as an opaque string so that the specific parameters can evolve separately 19 | * under the auspices of the Dynamic Native Ads API. Similarly, the ad markup served will be 20 | * structured according to that specification. The presence of a Native as a subordinate of the Imp 21 | * object indicates that this impression is offered as a native type impression. At the publisher’s 22 | * discretion, that same impression may also be offered as banner, video, and/or audio by also 23 | * including as Imp subordinates objects of those types. However, any given bid for the impression 24 | * must conform to one of the offered types. 25 | * 26 | * [OpenRTB Section 3.2.9](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=23) 27 | * 28 | * @property bidfloor Minimum bid for this native impression expressed in CPM. 29 | * @property request Request payload complying with the Native Ad Specification 30 | * @property ver Version of the Dynamic Native Ads API to which request complies. Highly recommended 31 | * for efficient parsing. 32 | * @property api List of supported API frameworks for this impression. If an API is not explicitly 33 | * listed, it is assumed not to be supported. 34 | * @property battr Set of creative attributes to block. 35 | */ 36 | @Serializable 37 | public class Native( 38 | @JvmField @SerialName("bidfloor") public var bidfloor: Float = 0f, 39 | @JvmField @SerialName("request") public var request: String? = null, 40 | @JvmField @SerialName("ver") public var ver: String? = null, 41 | @JvmField @SerialName("api") public var api: ByteArray? = null, 42 | @JvmField @SerialName("battr") public var battr: ByteArray? = null, 43 | @JvmField @SerialName("ext") public var ext: Extension? = null 44 | ) 45 | 46 | @Serializable 47 | public class Extension( 48 | @JvmField @SerialName("nimbus_native") public var nimbusNative : NimbusNative? = null 49 | ) 50 | 51 | @Serializable 52 | public class NimbusNative( 53 | @JvmField @SerialName("ver") public var ver: String = "1.2", 54 | @JvmField @SerialName("plcmttype") public var plcmttype: Byte?, 55 | @JvmField @SerialName("context") public var context: Byte?, 56 | @JvmField @SerialName("contextsubtype") public var contextsubtype: Byte?, 57 | @JvmField @SerialName("assets") public var assets: List, 58 | ) 59 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Publisher.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object describes the publisher of the media in which the ad will be displayed. 9 | * 10 | * The publisher is typically the seller in an OpenRTB transaction. 11 | * 12 | * [OpenRTB Section 3.2.15](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=26) 13 | * 14 | * @property name Publisher name (may be aliased at the publisher’s request). 15 | * @property domain Highest level domain of the publisher (e.g., "adsbynimbus.com"). 16 | * @property cat Array of IAB content categories that describe the publisher. 17 | * @see [OpenRTB Section 5.1](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=39) 18 | */ 19 | @Serializable 20 | public class Publisher( 21 | @JvmField @SerialName("name") public var name: String? = null, 22 | @JvmField @SerialName("domain") public var domain: String? = null, 23 | @JvmField @SerialName("cat") public var cat: Array? = null, 24 | ) 25 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Regs.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object contains any legal, governmental, or industry regulations that apply to the request. 9 | * 10 | * The coppa flag signals whether or not the request falls under the United States Federal Trade 11 | * Commission’s regulations for the United States Children’s Online Privacy Protection Act 12 | * ("COPPA"). 13 | * 14 | * [OpenRTB Section 3.2.3](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=17) 15 | * 16 | * @property coppa Flag indicating if this request is subject to the COPPA regulations established 17 | * by the USA FTC. 18 | * 0 = no 19 | * 1 = yes 20 | * @property ext Regs extension object unique to Nimbus 21 | * @see [OpenRTB Section 7.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=76) 22 | */ 23 | @Serializable 24 | public class Regs( 25 | @JvmField @SerialName("coppa") public var coppa: Byte = 0, 26 | @JvmField @SerialName("ext") public var ext: Extension = Extension(), 27 | ) { 28 | /** 29 | * Placeholder for exchange-specific extensions to OpenRTB. 30 | * 31 | * @property gdpr Flag indication if this request is subject to GDPR regulations. This flag will 32 | * be set automatically by Nimbus based on the received IP address. 33 | * @property us_privacy A publisher generated string representing compliance with CCPA. 34 | * The CCPA privacy string is a 4 character string in the following format: 35 | * 36 | * Integer - Privacy string version. 37 | * (Y, N, -) - Publisher has provided explicit user notice. 38 | * (Y, N, -) - User opted out of sale 39 | * (Y, N, -) - Publisher operating under the Limited Service Provider 40 | * Agreement 41 | * 42 | * If the user does not fall within a US Privacy jurisdiction, hyphens 43 | * should be used in the last three positions, generating this privacy 44 | * string: "1---" 45 | * @property gpp Global Privacy Platform (GPP) string that can be set to transmit privacy, consent, and consumer choice signals for relevant regulations. 46 | * @property gpp_sids GPP Section IDs representing the regulations relevant to the request. 47 | * @see [US Privacy String Format](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/Version%201.0/US%20Privacy%20String.md.us-privacy-string-format) 48 | */ 49 | @Serializable 50 | public class Extension( 51 | @JvmField @SerialName("gdpr") public var gdpr: Byte? = null, 52 | @JvmField @SerialName("us_privacy") public var us_privacy: String? = null, 53 | @JvmField @SerialName("gpp") public var gpp: String? = null, 54 | @JvmField @SerialName("gpp_sid") public var gpp_sids: String? = null, 55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Segment.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * Segment objects are essentially key-value pairs that convey specific units of data. 9 | * 10 | * The parent [Data] object is a collection of such values from a given data provider. The specific 11 | * segment names and value options must be published by the exchange a priori to its bidders. 12 | * 13 | * [OpenRTB Section 3.2.22](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=31) 14 | * 15 | * @property id ID of the data segment specific to the data provider. 16 | * @property name Name of the data segment specific to the data provider. 17 | * @property value String representation of the data segment value. 18 | * @property ext Placeholder for exchange-specific extensions to OpenRTB 19 | */ 20 | @Serializable 21 | public class Segment( 22 | @JvmField @SerialName("id") public val id: String? = null, 23 | @JvmField @SerialName("name") public val name: String? = null, 24 | @JvmField @SerialName("value") public val value: String? = null, 25 | @JvmField @SerialName("ext") public val ext: MutableMap = mutableMapOf() 26 | ) 27 | 28 | 29 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Signals.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * Custom signals for this request 9 | * @property session Session related signals as used by Nimbus 10 | */ 11 | @Serializable 12 | public class Signals( 13 | @JvmField @SerialName("session") public var session: Session = Session(), 14 | ) 15 | 16 | /** 17 | * Session related signals as used by Nimbus 18 | * @property depth Depth of the request 19 | * @property duration represents the duration in seconds since this session has started 20 | */ 21 | @Serializable 22 | public class Session( 23 | @JvmField @SerialName("depth") public var depth: Int = 0, 24 | @JvmField @SerialName("duration") public var duration: Long = 0, 25 | ) 26 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/Source.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | 6 | /** 7 | * This object describes the nature and behavior of the entity that is the source of the bid request 8 | * upstream from the exchange. 9 | * 10 | * The primary purpose of this object is to define post-auction or upstream decisioning when the 11 | * exchange itself does not control the final decision. A common example of this is header bidding, 12 | * but it can also apply to upstream server entities such as another RTB exchange, a mediation 13 | * platform, or an ad server combines direct campaigns with 3rd party demand in decisioning. 14 | * 15 | * [OpenRTB Section 3.2.2](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=16) 16 | * 17 | * @property ext Placeholder for exchange-specific extensions to OpenRTB. 18 | */ 19 | @Serializable 20 | public class Source( 21 | @SerialName("ext") public val ext: MutableMap = mutableMapOf() 22 | ) { 23 | 24 | /** Partner name that identifies the OM SDK integration */ 25 | public inline var omidpn: String 26 | get() = ext["omidpn"] ?: "" 27 | set(value) { ext["omidpn"] = value } 28 | 29 | /** Current version of the OM SDK integration */ 30 | public inline var omidpv: String 31 | get() = ext["omidpv"] ?: "" 32 | set(value) { ext["omidpv"] = value } 33 | } 34 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/request/User.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.request 2 | 3 | import kotlinx.serialization.SerialName 4 | import kotlinx.serialization.Serializable 5 | import kotlin.jvm.JvmField 6 | 7 | /** 8 | * This object contains information known or derived about the human user of the device (i.e., the 9 | * audience for advertising). 10 | * 11 | * The user id is an exchange artifact and may be subject to rotation or other privacy policies. 12 | * However, this user ID must be stable long enough to serve reasonably as the basis for frequency 13 | * capping and retargeting. 14 | * 15 | * [OpenRTB Section 3.2.20](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=30) 16 | * 17 | * @property age Age of the user 18 | * @property buyeruid Buyer-specific ID for the user as mapped by the exchange for the buyer. 19 | * Set to Facebook bidder token if integrating Facebook demand. 20 | * @property yob Year of birth as a 4-digit integer 21 | * @property gender The gender of this user. If omitted it is assumed to be unknown. 22 | * "male" = male 23 | * "female" = female. 24 | * @property keywords Comma separated list of keywords, interests, or intent. 25 | * @property custom_data Optional feature to pass bidder data that was set in the exchange’s cookie. 26 | * The string must be in base85 cookie safe characters and be in any format. 27 | * Proper JSON encoding must be used to include "escaped" quotation marks. 28 | * @property data Additional user data. Each data object represents a different data source. 29 | * @property ext User extension object unique to Nimbus 30 | * @see [OpenRTB Section 3.2.21](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=31) 31 | */ 32 | @Serializable 33 | public class User( 34 | @JvmField @SerialName("age") public var age: Int = 0, 35 | @JvmField @SerialName("buyeruid") public var buyeruid: String? = null, 36 | @JvmField @SerialName("yob") public var yob: Int = 0, 37 | @JvmField @SerialName("gender") public var gender: String? = null, 38 | @JvmField @SerialName("keywords") public var keywords: String? = null, 39 | @JvmField @SerialName("custom_data") public var custom_data: String? = null, 40 | @JvmField @SerialName("data") public var data: Array? = null, 41 | @JvmField @SerialName("ext") public var ext: Extension? = null, 42 | ) { 43 | 44 | /** 45 | * User extension object used by Nimbus 46 | * 47 | * @property consent Publisher provided GDPR consent string 48 | * @property facebook_buyeruid String token provided by the Facebook Audience Network to include FAN demand in 49 | * the auction. 50 | * @property unity_buyeruid String token provided by the Unity Ads SDK to include Unity demand 51 | * in the auction. Token is initialized when UnityAds is initialized 52 | * and the token and campaign is refreshed after the ad playback has 53 | * started. 54 | * @property vungle_buyeruid String token provided by the Vungle SDK to include Vungle in the auction. 55 | * @property mfx_buyerdata Map provided by MobileFuse SDK to include MobileFuse in the auction. 56 | * @property mintegral_sdk Map containing buyeruid and sdkv strings to include Mintegral in the auction. 57 | * @property moloco_buyeruid String token provided by Moloco SDK to include Moloco in the auction. 58 | * @property eids Collection of external user ids 59 | */ 60 | @Serializable 61 | public class Extension( 62 | @JvmField @SerialName("consent") public var consent: String? = null, 63 | @JvmField @SerialName("admob_gde_signals") public var admob_gde_signals: String? = null, 64 | @JvmField @SerialName("facebook_buyeruid") public var facebook_buyeruid: String? = null, 65 | @JvmField @SerialName("unity_buyeruid") public var unity_buyeruid: String? = null, 66 | @JvmField @SerialName("vungle_buyeruid") public var vungle_buyeruid: String? = null, 67 | @JvmField @SerialName("eids") public var eids: Set? = null, 68 | @JvmField @SerialName("mfx_buyerdata") public var mfx_buyerdata: Map? = null, 69 | @JvmField @SerialName("mintegral_sdk") public var mintegral_sdk: Map? = null, 70 | @JvmField @SerialName("moloco_buyeruid") public var moloco_buyeruid: String? = null, 71 | ) 72 | } 73 | 74 | /** An External User Id */ 75 | @Serializable 76 | public class EID( 77 | @JvmField @SerialName("source") public val source: String, 78 | @JvmField @SerialName("uids") public var uids: Set, 79 | ) { 80 | override fun equals(other: Any?): Boolean = other is EID && other.source == source 81 | 82 | override fun hashCode(): Int = source.hashCode() 83 | } 84 | 85 | /** Object representing the extended ID UID */ 86 | @Serializable 87 | public class UID( 88 | @JvmField @SerialName("id") public var id: String, 89 | @JvmField @SerialName("atype") public var atype: Int = 0, 90 | @JvmField @SerialName("ext") public var ext: Map = mutableMapOf() 91 | ) 92 | -------------------------------------------------------------------------------- /kotlin/src/commonMain/kotlin/com/adsbynimbus/openrtb/response/BidResponse.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb.response 2 | 3 | import com.adsbynimbus.openrtb.request.BidRequest 4 | import kotlinx.serialization.SerialName 5 | import kotlinx.serialization.Serializable 6 | import kotlinx.serialization.json.Json 7 | import kotlin.jvm.JvmField 8 | import kotlin.jvm.JvmOverloads 9 | import kotlin.jvm.JvmStatic 10 | 11 | /** 12 | * A winning bid response from Nimbus 13 | * 14 | * @property type The type of creative returned. This maps to one of "static", "video", or "native" 15 | * @property auction_id This unique auction id. Represented as a GUID. 16 | * @property adomain An optional list of the advertising domains associated with this ad. 17 | * @property bid_in_cents This winning auction's bid in cents. 18 | * @property bid_raw This winning auction's precise winning bid. 19 | * @property content_type The content type of this creative. "text/html" for static or a mime type 20 | * for video ads 21 | * @property crid The creative ID of this ad if known 22 | * @property height The height of the creative if available. Will not be set for Video or Native ads 23 | * @property width The width of the creative if available. Will not be set for Video or Native ads 24 | * @property is_interstitial Set to 1 if the original request was for an interstitial ad 25 | * @property markup The markup returned by Nimbus. Will be in the format of html for static or xml 26 | * VAST for video 27 | * @property network The network that won this auction 28 | * @property placement_id The winning placement id if the winning bid maps to a line item 29 | * @property is_mraid Set to 1 if Nimbus has determined the creative returned requests MRAID in the 30 | * creative markup 31 | * @property position The position from the request for this ad. 32 | * @property trackers Contains additional tracking urls for measurement. 33 | * @property duration The duration in seconds or 0 if unknown or another ad type. 34 | * @property exp Number of seconds a bidder can wait before rendering the impression. 35 | * @property external_notifications Contains urls used to notify external services. 36 | */ 37 | @Serializable 38 | public class BidResponse( 39 | @JvmField @SerialName("type") public val type: String, 40 | @JvmField @SerialName("auction_id") public val auction_id: String, 41 | @JvmField @SerialName("adomain") public val adomain: Array? = null, 42 | @JvmField @SerialName("bid_in_cents") public val bid_in_cents: Int = 0, 43 | @JvmField @SerialName("bid_raw") public val bid_raw: Float = 0f, 44 | @JvmField @SerialName("content_type") public val content_type: String? = null, 45 | @JvmField @SerialName("crid") public val crid: String? = null, 46 | @JvmField @SerialName("height") public val height: Int = 0, 47 | @JvmField @SerialName("width") public val width: Int = 0, 48 | @JvmField @SerialName("is_interstitial") public val is_interstitial: Byte = 0, 49 | @JvmField @SerialName("markup") public val markup: String, 50 | @JvmField @SerialName("network") public val network: String = "", 51 | @JvmField @SerialName("placement_id") public val placement_id: String? = null, 52 | @JvmField @SerialName("is_mraid") public val is_mraid: Byte = 0, 53 | @JvmField @SerialName("position") public val position: String, 54 | @JvmField @SerialName("trackers") public val trackers: Map> = emptyMap(), 55 | @JvmField @SerialName("duration") public val duration: Int = 0, 56 | @JvmField @SerialName("exp") public val exp: Int = -1, 57 | @JvmField @SerialName("external_notifications") public val external_notifications: Map = emptyMap(), 58 | ) { 59 | /** Urls to fire a request to when an impression is registered */ 60 | public val impression_trackers: Array? get() = trackers["impression_trackers"] 61 | /** Urls to fire a request to when a click is registered */ 62 | public val click_trackers: Array? get() = trackers["click_trackers"] 63 | /** Url to fire a request to when this bid wins an auction */ 64 | public val win_response: String? get() = external_notifications["win_response"] 65 | /** Url to fire a request to when this bid loses an auction */ 66 | public val loss_response: String? get() = external_notifications["loss_response"] 67 | 68 | public companion object { 69 | /** Decodes a BidResponse from a Json string using the built in serializer */ 70 | @JvmStatic @JvmOverloads 71 | public fun fromJson( 72 | json: String, 73 | jsonSerializer: Json = BidRequest.lenientSerializer, 74 | ): BidResponse = jsonSerializer.decodeFromString(serializer(), json) 75 | 76 | /** Encodes a BidResponse to a Json string using the built in serializer */ 77 | @JvmStatic @JvmOverloads 78 | public fun toJson( 79 | response: BidResponse, 80 | jsonSerializer: Json = BidRequest.lenientSerializer, 81 | ): String = jsonSerializer.encodeToString(serializer(), response) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /kotlin/src/commonTest/kotlin/BidResponseTest.kt: -------------------------------------------------------------------------------- 1 | package com.adsbynimbus.openrtb 2 | 3 | import com.adsbynimbus.openrtb.response.BidResponse 4 | import io.kotest.core.spec.style.StringSpec 5 | import io.kotest.matchers.collections.shouldContain 6 | import io.kotest.matchers.shouldBe 7 | import io.kotest.matchers.string.shouldContain 8 | import io.kotest.matchers.string.shouldStartWith 9 | 10 | const val testResponse = """ 11 | { 12 | "type": "native", 13 | "auction_id": "d07668d6-35ba-4870-a3cd-02b18fec1a12", 14 | "bid_in_cents": 405, 15 | "bid_raw": 4.053723, 16 | "content_type": "text/html; charset=utf-8", 17 | "is_interstitial": 1, 18 | "is_mraid": 1, 19 | "markup": "test_markup", 20 | "network": "test_network", 21 | "position": "test_position", 22 | "trackers": { 23 | "impression_trackers": [ 24 | "https://test.adsbynimbus.com/impression_tracker/" 25 | ], 26 | "click_trackers": [ 27 | "https://test.adsbynimbus.com/click_tracker/" 28 | ] 29 | }, 30 | "placement_id": "123456789", 31 | "duration": 15, 32 | "exp": 30, 33 | "external_notifications": { 34 | "win_response": "https://test.adsbynimbus.com/win_response/", 35 | "loss_response": "https://test.adsbynimbus.com/loss_response/auctionPrice=[AUCTION_PRICE]&auctionMinToWin=[AUCTION_MIN_TO_WIN]&winningSource=[WINNING_SOURCE]" 36 | } 37 | } 38 | """ 39 | 40 | class BidResponseTest : StringSpec({ 41 | 42 | lateinit var response: BidResponse 43 | 44 | beforeTest { 45 | response = BidResponse.fromJson(testResponse) 46 | } 47 | 48 | "BidResponse fromJson deserializes the type field" { 49 | response.type shouldBe "native" 50 | } 51 | 52 | "BidResponse fromJson deserializes the auction_id field" { 53 | response.auction_id shouldBe "d07668d6-35ba-4870-a3cd-02b18fec1a12" 54 | } 55 | 56 | "BidResponse fromJson deserializes the bid_in_cents field" { 57 | response.bid_in_cents shouldBe 405 58 | } 59 | 60 | "BidResponse fromJson deserializes the bid_raw field" { 61 | response.bid_raw shouldBe 4.053723f 62 | } 63 | 64 | "BidResponse fromJson deserializes the content_type field" { 65 | response.content_type shouldBe "text/html; charset=utf-8" 66 | } 67 | 68 | "BidResponse fromJson deserializes the is_interstitial field" { 69 | response.is_interstitial shouldBe 1 70 | } 71 | 72 | "BidResponse fromJson deserializes the is_mraid field" { 73 | response.is_mraid shouldBe 1 74 | } 75 | 76 | "BidResponse fromJson deserializes the markup field" { 77 | response.markup shouldBe "test_markup" 78 | } 79 | 80 | "BidResponse fromJson deserializes the network field" { 81 | response.network shouldBe "test_network" 82 | } 83 | 84 | "BidResponse fromJson deserializes the placement_id field" { 85 | response.placement_id shouldBe "123456789" 86 | } 87 | 88 | "BidResponse fromJson deserializes the position field" { 89 | response.position shouldBe "test_position" 90 | } 91 | 92 | "BidResponse fromJson deserializes click_trackers" { 93 | response.click_trackers!! shouldContain "https://test.adsbynimbus.com/click_tracker/" 94 | } 95 | 96 | "BidResponse fromJson deserializes impression_trackers" { 97 | response.impression_trackers!! shouldContain "https://test.adsbynimbus.com/impression_tracker/" 98 | } 99 | 100 | "BidResponse fromJson deserializes the duration field" { 101 | response.duration shouldBe 15 102 | } 103 | 104 | "BidResponse fromJson deserializes the exp field" { 105 | response.duration shouldBe 15 106 | } 107 | 108 | "BidResponse fromJson deserializes win urls" { 109 | response.win_response shouldBe "https://test.adsbynimbus.com/win_response/" 110 | } 111 | 112 | "BidResponse fromJson deserializes loss urls" { 113 | response.loss_response shouldStartWith "https://test.adsbynimbus.com/loss_response/" 114 | response.loss_response shouldContain "auctionPrice=[AUCTION_PRICE]" 115 | response.loss_response shouldContain "auctionMinToWin=[AUCTION_MIN_TO_WIN]" 116 | response.loss_response shouldContain "winningSource=[WINNING_SOURCE]" 117 | } 118 | }) 119 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | @file:Suppress("UnstableApiUsage") 2 | 3 | pluginManagement { 4 | repositories { 5 | google { 6 | mavenContent { 7 | includeGroupAndSubgroups("androidx") 8 | includeGroupAndSubgroups("com.android") 9 | includeGroupAndSubgroups("com.google") 10 | } 11 | } 12 | mavenCentral() 13 | gradlePluginPortal() 14 | } 15 | } 16 | 17 | val androidGradleOverride = with(providers) { 18 | gradleProperty("android.studio.version").flatMap { gradleProperty("android.gradle") } 19 | } 20 | 21 | dependencyResolutionManagement { 22 | repositories { 23 | google { 24 | mavenContent { 25 | includeGroupAndSubgroups("androidx") 26 | includeGroupAndSubgroups("com.android") 27 | includeGroupAndSubgroups("com.google") 28 | } 29 | } 30 | mavenCentral() 31 | } 32 | versionCatalogs.configureEach { 33 | if (androidGradleOverride.isPresent) version("android", androidGradleOverride.get()) 34 | } 35 | } 36 | 37 | rootProject.name = "nimbus-openrtb" 38 | 39 | include("kotlin") 40 | --------------------------------------------------------------------------------