--- URL: "https://docs.revosurge.com/" LLMS_URL: "https://docs.revosurge.com/index.md" layout: "page" title: "RevoSurge Platform Docs" head: - 0: "meta" 1: http-equiv: "refresh" content: "0;url=/en/" --- Redirecting to [English](/en/)... --- URL: "https://docs.revosurge.com/docs/superpowers/plans/2026-03-18-exchange-rate-reference" LLMS_URL: "https://docs.revosurge.com/docs/superpowers/plans/2026-03-18-exchange-rate-reference.md" --- # Exchange Rate Reference Implementation Plan > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Add a new English `Reference Data` docs page that loads monthly exchange-rate JSON from a CDN at runtime, defaults to the latest month, and lets readers switch months in a full table view. **Architecture:** Implement one page-specific Vue component at `.vitepress/theme/components/ExchangeRatesTable.vue`. The Markdown page passes a single `indexUrl` prop; the component fetches `index.json`, derives monthly file URLs from the same directory, validates both payload shapes, caches month payloads in memory, and renders loading, error, empty, and table states. Update the English sidebar to expose a new top-level `Reference Data` group containing `Exchange Rate Reference`. **Tech Stack:** VitePress 2, Vue 3 with ` ``` - [ ] **Step 2: Create the new English page and import the component locally** Create `en/reference-data/exchange-rates.md` and make the confirmed production CDN URL explicit in one local constant: ```md --- title: Exchange Rate Reference description: Browse monthly exchange-rate reference data by month. --- # Exchange Rate Reference Monthly exchange-rate reference data published from the internal finance pipeline. ``` Set `exchangeRatesIndexUrl` to the exact production `index.json` URL confirmed in Preconditions. Keep it as a single local constant in this page so the data source remains obvious and page-scoped. - [ ] **Step 3: Add the page to the English sidebar** Modify `.vitepress/config/en.ts` to insert a new top-level group: ```ts { text: 'Reference Data', link: '/en/reference-data/exchange-rates', collapsed: false, items: [ { text: 'Exchange Rate Reference', link: '/en/reference-data/exchange-rates' } ] } ``` Place it near the end of the existing sidebar groups, before `LLM Resources`, so it reads like reference material instead of product onboarding. - [ ] **Step 4: Run the build to verify the new route and import path compile** Run: `npm run build` Expected: - Exit code `0` - VitePress builds successfully - No Markdown import errors - No Vue SFC compile errors - [ ] **Step 5: Commit the route wiring** ```bash git add .vitepress/theme/components/ExchangeRatesTable.vue en/reference-data/exchange-rates.md .vitepress/config/en.ts git commit -m "feat: add exchange rate reference page shell" ``` ### Task 2: Implement runtime loading, validation, and the table UI **Files:** - Modify: `.vitepress/theme/components/ExchangeRatesTable.vue` - Test: `npm run build` - [ ] **Step 1: Add strict payload types and validation helpers** Expand the component script with explicit runtime guards instead of trusting raw JSON: ```ts import { computed, onMounted, ref } from 'vue' type IndexPayload = { latestMonth: string months: string[] } type RateRow = { currency: string rate: number } type MonthPayload = { month: string baseCurrency: string generatedAt: string rates: RateRow[] } function assertIndexPayload(value: unknown): IndexPayload { if (!value || typeof value !== 'object') { throw new Error('Invalid exchange-rate index payload.') } const payload = value as Record if (typeof payload.latestMonth !== 'string') { throw new Error('Exchange-rate index is missing latestMonth.') } if ( !Array.isArray(payload.months) || payload.months.some( (month) => typeof month !== 'string' || !/^\d{4}-\d{2}$/.test(month) ) ) { throw new Error('Exchange-rate index has invalid months.') } if (!payload.months.includes(payload.latestMonth)) { throw new Error('Exchange-rate index latestMonth is not present in months.') } return { latestMonth: payload.latestMonth, months: payload.months as string[] } } function assertMonthPayload(value: unknown, requestedMonth: string): MonthPayload { if (!value || typeof value !== 'object') { throw new Error('Invalid monthly exchange-rate payload.') } const payload = value as Record if (payload.month !== requestedMonth) { throw new Error(`Exchange-rate month mismatch for ${requestedMonth}.`) } if (typeof payload.baseCurrency !== 'string') { throw new Error('Monthly exchange-rate payload is missing baseCurrency.') } if (typeof payload.generatedAt !== 'string') { throw new Error('Monthly exchange-rate payload is missing generatedAt.') } if ( !Array.isArray(payload.rates) || payload.rates.some((row) => { if (!row || typeof row !== 'object') return true const rateRow = row as Record return typeof rateRow.currency !== 'string' || typeof rateRow.rate !== 'number' }) ) { throw new Error('Monthly exchange-rate payload has invalid rates.') } return { month: payload.month as string, baseCurrency: payload.baseCurrency as string, generatedAt: payload.generatedAt as string, rates: payload.rates as RateRow[] } } ``` Use thrown `Error` instances for invalid payloads so the component can render one consistent error state. - [ ] **Step 2: Add reactive state, URL derivation, and month cache** Introduce only the state needed for this page: ```ts const months = ref([]) const selectedMonth = ref('') const monthData = ref(null) const loadingIndex = ref(true) const loadingMonth = ref(false) const errorMessage = ref('') const monthCache = new Map() const baseUrl = computed(() => new URL('.', props.indexUrl).toString()) function monthUrl(month: string): string { return new URL(`${month}.json`, baseUrl.value).toString() } ``` Sort `months` in descending lexicographic order as soon as the index payload is accepted. - [ ] **Step 3: Implement `loadIndex`, `loadMonth`, `initialize`, and `retry`** Add one code path for first load and one for month switching: ```ts async function loadIndex(): Promise { const response = await fetch(props.indexUrl) if (!response.ok) throw new Error('Failed to load exchange-rate index.') return assertIndexPayload(await response.json()) } async function loadMonth(month: string): Promise { if (monthCache.has(month)) { monthData.value = monthCache.get(month) ?? null selectedMonth.value = month errorMessage.value = '' return } loadingMonth.value = true errorMessage.value = '' try { const response = await fetch(monthUrl(month)) if (!response.ok) throw new Error(`Failed to load exchange rates for ${month}.`) const payload = assertMonthPayload(await response.json(), month) monthCache.set(month, payload) monthData.value = payload selectedMonth.value = month } catch (error) { errorMessage.value = error instanceof Error ? error.message : 'Failed to load exchange rates.' } finally { loadingMonth.value = false } } async function initialize(): Promise { loadingIndex.value = true errorMessage.value = '' try { const indexPayload = await loadIndex() months.value = [...indexPayload.months].sort().reverse() await loadMonth(indexPayload.latestMonth) } catch (error) { errorMessage.value = error instanceof Error ? error.message : 'Failed to load exchange-rate index.' } finally { loadingIndex.value = false } } ``` Call `initialize()` in `onMounted()`. Expose one retry action that calls `initialize()` if no month has loaded yet, otherwise retries `loadMonth(selectedMonth.value)`. - [ ] **Step 4: Replace the shell template with the real stateful UI** Render exactly these sections inside the component template: ```vue ``` Keep the template narrow. Do not add charts, filters, or search. - [ ] **Step 5: Add scoped styles for readability and mobile overflow** Add scoped CSS inside `.vitepress/theme/components/ExchangeRatesTable.vue` for: - A padded state container with subtle border/background - A compact toolbar row - Readable metadata chips or inline blocks - A horizontally scrollable table wrapper - Table header and row borders using VitePress color tokens - A simple retry button that matches the theme Minimum structure: ```css .exchange-rates__table-wrap { overflow-x: auto; } .exchange-rates__table { width: 100%; min-width: 420px; border-collapse: collapse; } .exchange-rates__table th, .exchange-rates__table td { padding: 12px 14px; border-bottom: 1px solid var(--vp-c-divider); text-align: left; } ``` Keep all new styling inside the component unless a real global style need appears. - [ ] **Step 6: Run the build after the component implementation** Run: `npm run build` Expected: - Exit code `0` - No TypeScript-in-SFC errors - No VitePress SSR build errors - [ ] **Step 7: Commit the runtime implementation** ```bash git add .vitepress/theme/components/ExchangeRatesTable.vue git commit -m "feat: implement exchange rate table runtime" ``` ### Task 3: Manually verify states and finish the page **Files:** - Modify if needed: `.vitepress/theme/components/ExchangeRatesTable.vue` - Modify if needed: `en/reference-data/exchange-rates.md` - Modify if needed: `.vitepress/config/en.ts` - Test: `npm run dev`, `npm run build` - [ ] **Step 1: Start the local docs server** Run: `npm run dev` Expected: - VitePress prints a local URL such as `http://localhost:5173/` - The new page is reachable at `/en/reference-data/exchange-rates` - [ ] **Step 2: Verify the happy path in the browser** Open the page and confirm: - The latest month loads automatically - The month selector is populated - Metadata shows month, base currency, and generation timestamp - The full table renders with all rows from the selected month JSON - [ ] **Step 3: Verify month switching and cache reuse** Switch to an older month, then switch back to the original month. Expected: - Metadata changes with the selected month - Table rows update with the selected month payload - The second visit to a previously loaded month reuses the in-memory cache instead of issuing a new request Use the browser Network panel to confirm that switching back to an already loaded month does not issue another `YYYY-MM.json` request. - [ ] **Step 4: Verify the blocking index error state** Temporarily change `exchangeRatesIndexUrl` in `en/reference-data/exchange-rates.md` so it points at a missing JSON file in the same CDN directory. For example, keep the same base path but replace `index.json` with `does-not-exist.json`. Refresh the page and confirm: - The feature shows the blocking error state - The retry button is visible Restore the real `indexUrl` immediately after verification. - [ ] **Step 5: Verify the month-file error state** Temporarily change the component `monthUrl()` helper to return a missing file name: ```ts function monthUrl(month: string): string { return new URL(`${month}-missing.json`, baseUrl.value).toString() } ``` Load the page and confirm: - The month selector still renders - The table area shows the month-level error state - The retry button is visible Restore the real `monthUrl()` implementation immediately after verification. - [ ] **Step 6: Verify the empty state** If the CDN can provide a temporary empty month fixture, use it. Otherwise, temporarily stub an empty month payload inside `loadMonth()` after validation: ```ts monthData.value = { ...payload, rates: [] } ``` Confirm the empty-state message appears instead of the table, then restore the real assignment: ```ts monthData.value = payload ``` - [ ] **Step 7: Run the final build** Run: `npm run build` Expected: - Exit code `0` - Final implementation builds cleanly after all temporary verification edits are restored - [ ] **Step 8: Commit the final verified version** ```bash git add .vitepress/theme/components/ExchangeRatesTable.vue en/reference-data/exchange-rates.md .vitepress/config/en.ts git commit -m "feat: add exchange rate reference" ``` --- URL: "https://docs.revosurge.com/docs/superpowers/specs/2026-03-18-exchange-rates-design" LLMS_URL: "https://docs.revosurge.com/docs/superpowers/specs/2026-03-18-exchange-rates-design.md" --- # Monthly Exchange Rates Page Design ## Summary Add one English documentation page that displays a monthly exchange-rate table. The data will not be fetched during the VitePress build. Instead, an internal DAG will periodically fetch the private source data, transform it into static JSON files, and publish those files to a CDN. The docs page will load the latest month at runtime in the browser, allow the reader to switch months, and render the full rate table for the selected month. This design is intentionally narrow. It does not introduce a shared data layer or a reusable cross-page component system. It implements one page-specific feature with one page-specific Vue component. ## Context This repository is a static VitePress site deployed to GitHub Pages. The current deployment workflow runs on GitHub-hosted runners and builds static output only. That environment should not be responsible for reaching private Kubernetes services. The chosen integration model is: 1. Internal DAG fetches private API data on a schedule. 2. DAG writes frontend-ready JSON to a CDN. 3. The docs page reads the CDN JSON at runtime in the browser. This keeps private network access, authentication, and API shaping outside the docs repository. ## Goals - Show a monthly exchange-rate table on one docs page. - Default to the latest available month. - Allow users to switch months and see the full dataset for that month. - Keep the docs site purely static and browser-driven for this feature. - Keep the implementation simple and local to this page. ## Non-Goals - No build-time fetch from the exchange-rate data source. - No GitHub Actions access to private Kubernetes services. - No generic shared data-fetching framework. - No global component registration for this feature. - No charting, CSV export, filtering, or search in the first version. - No Simplified Chinese or Traditional Chinese versions in the first version. - No compatibility layer for multiple JSON schema versions. ## File Layout The implementation will use these files: - `en/reference-data/exchange-rates.md` - `.vitepress/theme/components/ExchangeRatesTable.vue` - `.vitepress/config/en.ts` `en/reference-data/exchange-rates.md` will contain the page copy, import the page-specific component locally, and pass one required prop: `indexUrl`. `.vitepress/config/en.ts` will add a top-level English sidebar group named `Reference Data`, with a page entry named `Exchange Rate Reference`. The component will not be registered globally in `.vitepress/theme/index.ts`. ## Runtime Architecture The page will import `ExchangeRatesTable.vue` and render it once. The component will accept one required prop, `indexUrl`, which points to the CDN index file. The component will derive monthly file URLs from the same directory as `indexUrl`. The component will own the runtime behavior for this page: 1. On client mount, request the CDN `index.json`. 2. Read the latest month and the available month list from that file. 3. Select the latest month by default. 4. Request the selected month JSON file. 5. Render the month metadata and the full rate table. 6. When the user changes the month, request the corresponding month JSON file and re-render the table. The component will perform all network requests in the browser only. It will not fetch during SSR or the static build. ## CDN Data Contract The docs page will consume two JSON shapes. ### Index file Location pattern: `https:///exchange-rates/index.json` Required shape: ```json { "latestMonth": "2026-03", "months": ["2026-03", "2026-02", "2026-01"] } ``` Rules: - `latestMonth` is required and must match one entry in `months`. - `months` is required and contains month identifiers in `YYYY-MM` format. - The page will sort the months in descending lexicographic order before rendering. `YYYY-MM` is chosen specifically so simple string sorting is valid. ### Monthly file Location pattern: `https:///exchange-rates/YYYY-MM.json` Required shape: ```json { "month": "2026-03", "baseCurrency": "USD", "generatedAt": "2026-03-01T00:00:00Z", "rates": [ { "currency": "EUR", "rate": 0.92 }, { "currency": "JPY", "rate": 149.31 } ] } ``` Rules: - `month` is required and must equal the requested `YYYY-MM`. - `baseCurrency` is required. - `generatedAt` is required and must be an ISO-8601 UTC timestamp string. - `rates` is required. - Each `rates` item must contain: - `currency`: currency code string - `rate`: numeric exchange rate The page will treat this schema as strict. If required fields are missing or malformed, the component will show an error state instead of attempting to infer or repair the data. ## Publish and Caching Requirements The feature depends on the CDN behaving predictably. Required external conditions: - Files are publicly reachable over HTTPS. - The CDN serves the JSON with `Content-Type: application/json`. - The CDN allows browser access from `https://docs.revosurge.com` via CORS, or allows all origins. Publishing rules for the DAG: - Upload the new monthly file first. - Update `index.json` last. This prevents the docs page from seeing a new `latestMonth` before the corresponding monthly file exists on the CDN. Caching guidance: - `index.json` should have a short cache lifetime because it changes when a new month becomes available. - Monthly files should have a longer cache lifetime because a month file is expected to be immutable after publication. ## Page UX The page will display: - A month selector. - The selected month. - The base currency. - The data generation timestamp in UTC. - A full table with one row per currency. The initial page state is: - Show a loading state while `index.json` and the first monthly file are being requested. - After both requests succeed, show the month selector and the table. Month switching behavior: - When a user selects another month, the component requests only that month file. - The component does not re-request `index.json` during month switching. The table will use a horizontally scrollable wrapper on smaller screens so the page remains usable on mobile without collapsing the dataset into cards. ## Error and Empty States The page will support three explicit UI states: - `loading` - `error` - `empty` Behavior rules: - If `index.json` fails to load or is invalid, show a blocking error state for the whole feature area. - If the selected month file fails to load or is invalid, keep the month selector visible and show an error state for the table area with a retry action. - If the selected month file loads successfully but `rates` is empty, show an empty state message instead of the table. The first version does not need nuanced partial recovery beyond these rules. ## Client Behavior The component will keep a simple in-memory cache keyed by month. If a user switches from one month to another and then back, the component should reuse the already loaded JSON from memory during that page session. The cache does not need persistence across reloads, tabs, or browser sessions. The component will not use local storage, indexed DB, or service workers. ## Implementation Boundaries This feature should remain page-specific. Explicit boundaries: - Use a single page-specific Vue component. - Import the component directly into the exchange-rates page. - Do not create a shared hook, shared store, or multi-endpoint abstraction. - Do not add this feature to `.vitepress/theme/index.ts` unless a future requirement creates a real need for broader registration. ## Verification Requirements Implementation is complete when all of the following are true: - The English page exists at `en/reference-data/exchange-rates.md`. - The English sidebar contains a top-level `Reference Data` group with an `Exchange Rate Reference` entry. - Opening the page loads the latest available month by default. - Switching months updates the displayed metadata and table correctly. - The `loading`, `error`, and `empty` states are each supported. - The table remains usable on mobile through horizontal scrolling. - `npm run build` succeeds without SSR or VitePress errors. Manual verification is sufficient for the first version. No dedicated test framework is required for this feature. ## Recommendation For Planning When writing the implementation plan, keep the work split into three focused parts: 1. Create the page-specific Vue component and runtime fetch logic. 2. Add the new English docs page and sidebar entry. 3. Verify runtime behavior, responsive layout, and build success. --- URL: "https://docs.revosurge.com/en" LLMS_URL: "https://docs.revosurge.com/en.md" title: "RevoSurge Platform Docs" layout: "home" description: "RevoSurge docs. Performance campaigns, first-party tracking, account, API." hero: name: "RevoSurge" text: "Platform Docs" tagline: "A unified platform for running performance campaigns and measuring outcomes with first-party data." actions: - theme: "brand" text: "Get started" link: "/en/growth/getting-started" - theme: "alt" text: "Overview" link: "/en/revosurge/welcome" features: - title: "Performance Campaigns" details: "Launch and optimize campaigns in AdWave with guided setup workflows and real-time validation." - title: "First-Party Tracking" details: "Install trackers, validate events, and measure outcomes using DataPulse analytics." - title: "Account Management" details: "Manage your account, wallet, team members, and permissions all in one place." - title: "API Integration" details: "Automate campaign management, reporting, and audience segmentation with comprehensive APIs." --- --- URL: "https://docs.revosurge.com/en/adflow/adflowjs-debugger" LLMS_URL: "https://docs.revosurge.com/en/adflow/adflowjs-debugger.md" title: "adflow.js Debugger" description: "Test adflow.js in-browser. Configure URL, account ID, placement to validate S2S bidding." --- # adflow.js Test Test the adflow.js one-script integration: just include the script and place iframe tags to enable Prebid S2S bidding. ## Configuration
## Code Preview Auto-generated integration code based on the parameters above. Publishers can copy and paste to integrate:

Generated HTML Code

## Test Status

Execution Status

Script LoadWaiting
Config ReadWaiting
Slot DiscoveryWaiting
Prebid.js LoadWaiting
S2S AuctionWaiting
Ad RenderingWaiting

Runtime Config

Status: Not Started
## Ad Preview

Test Ad Slot (300x250)

data-placement-id="test-placement-1"
Waiting for auction...
## Logs
--- URL: "https://docs.revosurge.com/en/adflow/integration-guide" LLMS_URL: "https://docs.revosurge.com/en/adflow/integration-guide.md" title: "Publisher Integration Guide" description: "Integrate adflow.js or Prebid S2S to place ads. adflow.js or S2S step-by-step guide." --- # Publisher Integration Guide This guide covers how to integrate ads into your website. We offer two integration approaches: [adflow.js Quick Integration](#adflow-sdk) (recommended, simplest) and [S2S Configuration](#s2s-integration) (manual setup, more flexible). ## Integration Modes Comparison | Dimension | adflow.js Quick Integration | S2S Configuration | | --- | --- | --- | | **Complexity** | Minimal — just 2 lines of HTML | Moderate — requires JS coding | | **Prebid.js Knowledge** | Not required | Required | | **Ad Formats** | Banner | Banner / Video / Native / Multi-Format | | **Rendering** | Automatic iframe rendering | Full control, custom rendering supported | | **Configuration** | HTML data attributes | Full Prebid.js config API | | **Preferred Deal** | Supported | Supported | | **Advanced Features** | Basic configuration | Price Granularity, User Sync, First Party Data, etc. | | **Recommended For** | Quick launch, simple pages, no frontend dev resources | Production environments, complex requirements, fine-grained control | ## adflow.js Quick Integration {#adflow-sdk} adflow.js is a self-contained JavaScript SDK that encapsulates all Prebid.js S2S bidding logic into a single script. Publishers only need to include one ` ``` **2. Place Ad Slots** Add ` ``` adflow.js automatically handles the entire flow: Load Prebid.js → Configure S2S → Discover ad slots on the page → Run auction → Render winning ads. ### Script Attributes {#adflow-script-attrs} The following data attributes are supported on the `

My Website

``` ::: info Debugging Add the `data-debug` attribute to the ` ``` **2. Place Ad Slots** Add ` ``` ### Script Attributes {#adflow-tma-script-attrs} The following data attributes are supported on the `

My Mini App

``` ::: info Debugging Add the `data-debug` attribute to the ` ``` ## S2S Configuration {#s2s-integration} For more granular control, or if you need to customize Prebid.js configuration (ad formats, first-party data, user sync, etc.), use the manual S2S configuration approach. This requires including Prebid.js on your page and writing bidding code. [S2S Debugger](/en/adflow/s2s-debugger) ### Quick Start {#quick-start} #### Prerequisites - An AdFlow account with bid parameters obtained - A deployed website with pages available for ad placement #### Step-by-Step Integration **1. Include Prebid.js** Load Prebid.js in your page's ``. It's recommended to use a custom build (containing only the Bidder Adapters you need) to reduce file size. ```html ``` **2. Define Ad Slots** Place ad containers on your page. The `id` must match the `code` in the Prebid.js configuration. ```html
``` **3. Configure Prebid.js** Initialize Prebid.js and add Ad Units. Replace `placementId` with the value obtained from your AdFlow dashboard. ```js var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { var adUnits = [{ code: 'ad-slot-1', // Matches the div id on the page mediaTypes: { banner: { sizes: [[300, 250], [336, 280]] } }, bids: [{ bidder: 'revosurge', params: { placementId: 'your-placement-id' // Replace with your Placement ID } }] }]; pbjs.addAdUnits(adUnits); pbjs.requestBids({ timeout: 2000, bidsBackHandler: function() { // Bidding complete, send to ad server sendAdServerRequest(); } }); }); ``` **4. Render Ads** After bidding completes, render the winning ad onto the page. ```js function sendAdServerRequest() { // If using GAM, refer to the "Ad Server Integration" section // Below is a simple rendering approach without an ad server var adSlots = ['ad-slot-1']; adSlots.forEach(function(slotId) { var highestBid = pbjs.getHighestCpmBids(slotId)[0]; if (highestBid) { // Fire nurl callback to notify ad server of win if (highestBid.nurl) { var nurlWithPrice = highestBid.nurl.replace('${AUCTION_PRICE}', highestBid.cpm || 0); fetch(nurlWithPrice, { method: 'GET' }).catch(function() {}); } var adContainer = document.getElementById(slotId); var iframe = document.createElement('iframe'); iframe.style.cssText = 'border:0;width:' + highestBid.width + 'px;height:' + highestBid.height + 'px;'; adContainer.appendChild(iframe); var iframeDoc = iframe.contentWindow.document; iframeDoc.write(highestBid.ad); iframeDoc.close(); } }); } ``` #### Full Example {#full-example} ::: tip Below is a minimal complete page example that you can copy and use directly. ::: ```html My Website

My Website

``` ### Ad Unit Configuration {#ad-units} Prebid.js supports multiple ad formats. Below are the formats supported by the Revosurge Bidder and their configuration. #### Banner Ads {#banner} The most common ad format, suitable for fixed-size display ads. ```js { code: 'banner-slot', mediaTypes: { banner: { sizes: [ [300, 250], // Medium Rectangle [336, 280], // Large Rectangle [728, 90], // Leaderboard [970, 250] // Billboard ] } }, bids: [{ bidder: 'revosurge', params: { placementId: 'your-placement-id' } }] } ``` #### Video Ads {#video} Suitable for Outstream or Instream video ads. ```js { code: 'video-slot', mediaTypes: { video: { playerSize: [640, 480], context: 'outstream', // 'outstream' or 'instream' mimes: ['video/mp4', 'video/webm'], protocols: [1, 2, 3, 4, 5, 6], playbackmethod: [2], // Auto-play muted maxduration: 30 } }, bids: [{ bidder: 'revosurge', params: { placementId: 'your-video-placement-id' } }] } ``` #### Native Ads {#native} Native ads blend with your page content style, providing a better user experience. ```js { code: 'native-slot', mediaTypes: { native: { title: { required: true, len: 80 }, body: { required: true, len: 200 }, image: { required: true, sizes: [300, 250] }, icon: { required: false, sizes: [50, 50] }, cta: { required: false }, sponsoredBy: { required: true } } }, bids: [{ bidder: 'revosurge', params: { placementId: 'your-native-placement-id' } }] } ``` #### Multi-Format Ads {#multi-format} A single ad slot supports multiple formats, letting the system choose the optimal ad type. ```js { code: 'multi-format-slot', mediaTypes: { banner: { sizes: [[300, 250]] }, video: { playerSize: [300, 250], context: 'outstream', mimes: ['video/mp4'] } }, bids: [{ bidder: 'revosurge', params: { placementId: 'your-multi-format-placement-id' } }] } ``` ### Server-to-Server (S2S) Mode {#s2s-config} #### S2S Overview {#s2s-overview} In S2S mode, Prebid.js no longer sends requests directly from the browser to each Bidder. Instead, requests are sent to the Prebid Server, which handles bidding on the server side. Benefits include: - **Better page performance** — Fewer HTTP requests from the browser - **Lower latency** — Server-side network is faster than client-side - **Better privacy compliance** — Less client-side data transmission #### S2S Setup {#s2s-setup} ```js pbjs.que.push(function() { pbjs.setConfig({ s2sConfig: { accountId: 'your-account-id', bidders: ['revosurge'], adapter: 'prebidServer', enabled: true, endpoint: 'https://prebid-server.revosurge.com/openrtb2/auction', syncEndpoint: 'https://prebid-server.revosurge.com/cookie_sync', timeout: 3000 } }); }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `accountId` | String | Required | Account ID assigned by Revosurge | | `bidders` | Array | Required | List of Bidders to use via S2S | | `adapter` | String | Required | Must be `'prebidServer'` | | `enabled` | Boolean | Required | Set to `true` to enable S2S | | `endpoint` | String | Required | Prebid Server Auction endpoint | | `syncEndpoint` | String | Optional | Cookie Sync endpoint | | `timeout` | Number | Optional | S2S request timeout in milliseconds, default `1000` | ::: info In S2S mode, the Ad Unit `bids` configuration remains the same. Prebid.js will automatically forward requests for Bidders listed in `s2sConfig.bidders` to Prebid Server. ::: ### Ad Server Integration (GAM) {#s2s-gam} If the publisher uses Google Ad Manager (GAM) to manage inventory, the recommended pattern is Prebid.js + S2S + GPT. Revosurge still participates through `s2sConfig`, then Prebid writes price key-values into GPT, and GAM decides which line item finally serves. Flow: 1. Load GPT and Prebid.js, then define the GAM slot on the page. 2. Call `disableInitialLoad()` in GPT so the slot does not request too early. 3. Configure Revosurge through `pbjs.setConfig({ s2sConfig })`. 4. After bidding completes, call `pbjs.setTargetingForGPTAsync()` to write header bidding keys. 5. Finally call `googletag.pubads().refresh()` so GAM can return the final ad. #### Example: Prebid S2S + GAM Managed ```html Prebid S2S + GAM
``` ### Bid Parameters {#bidder-params} The Revosurge Bidder supports the following parameters: | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `placementId` | String | Required | Ad placement ID, obtained after creating a placement in the AdFlow dashboard | Example: ```js bids: [{ bidder: 'revosurge', params: { placementId: 'abc123' } }] ``` ### Preferred Deal {#preferred-deal} #### Overview {#deal-overview} Preferred Deal is a private programmatic buying arrangement (PMP - Private Marketplace) that allows publishers to establish priority trading agreements with specific advertisers or buyers. After configuring Preferred Deals in Prebid.js, the system will prioritize matching these private deals while still participating in open auctions. ::: tip Benefits Preferred Deals typically yield higher CPM while ensuring ad quality and brand safety. ::: #### Configuration Methods {#deal-methods} Prebid.js supports two methods for configuring Preferred Deals: **Method 1: Add dealId to Bidder Params (Simple Method)** Add the `dealId` parameter directly in the `params` of `bids`: ```js bids: [{ bidder: 'revosurge', params: { placementId: 'your-placement-id', dealId: 'your-preferred-deal-id' // Add Deal ID } }] ``` **Method 2: Use ortb2Imp to Configure PMP** Use the OpenRTB standard `ortb2Imp.pmp` object for configuration, supporting richer parameters and multiple deals: ```js { code: 'ad-slot-1', mediaTypes: { banner: { sizes: [[300, 250], [336, 280]] } }, bids: [{ bidder: 'revosurge', params: { placementId: 'your-placement-id' } }], ortb2Imp: { pmp: { private_auction: 0, // 0=allow open auction, 1=private deals only deals: [{ id: 'deal-12345', // Deal ID (required) bidfloor: 5.0, // Floor price (optional) bidfloorcur: 'USD', // Floor currency (optional) at: 1, // Auction type: 1=first price, 2=second price wseat: ['advertiser-seat'], // Allowed buyer seats (optional) wadomain: ['advertiser.com'] // Allowed advertiser domains (optional) }] } } } ``` **PMP Parameters** | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `deals[].id` | String | Required | Deal ID, provided by advertiser or SSP | | `deals[].bidfloor` | Number | Optional | Floor price; bids below this will be rejected | | `deals[].bidfloorcur` | String | Optional | Floor price currency (e.g., USD, CNY), default USD | | `deals[].at` | Number | Optional | Auction type: 1=first price, 2=second price | | `private_auction` | Number | Optional | 0=allow open auction, 1=private deals only, default 0 | | `deals[].wseat` | Array | Optional | Allowed buyer seat whitelist | | `deals[].wadomain` | Array | Optional | Allowed advertiser domain whitelist | #### Configuration Best Practices - **Use the ortb2Imp method** — More standardized and supports advanced features - **Set private_auction: 0** — Allow Preferred Deals and open auctions to participate together, increasing fill rate - **Configure multiple Deals** — Set up multiple deals for the same ad slot to increase matching opportunities - **Set reasonable floor prices** — bidfloor should be set based on actual conditions; setting it too high will reduce fill rate - **Combine with S2S** — Preferred Deals perform better in Server-to-Server mode ### Advanced Configuration {#advanced} #### Price Granularity {#price-granularity} Price granularity determines how bid amounts are rounded, affecting the number of Line Items needed and revenue precision. ```js pbjs.setConfig({ priceGranularity: 'medium' // 'low' | 'medium' | 'high' | 'auto' | 'dense' | custom }); ``` | Level | Range | Increment | | --- | --- | --- | | `low` | $0 - $5 | $0.50 | | `medium` | $0 - $20 | $0.10 | | `high` | $0 - $20 | $0.01 | | `auto` | $0 - $20 | Varies | | `dense` | $0 - $20 | Varies (denser) | #### Timeout Settings {#timeout} ```js pbjs.setConfig({ bidderTimeout: 2000 // In milliseconds, recommended 1500-3000 }); ``` ::: info Setting the timeout too short may cause Bidders to not respond in time (lower bid rate). Setting it too long may affect user experience. It's recommended to set it between **1500-3000ms** based on your actual network conditions. ::: #### User Sync {#user-sync} User sync allows Bidders to identify users, improving bidding performance. ```js pbjs.setConfig({ userSync: { iframeEnabled: true, pixelEnabled: true, syncsPerBidder: 5, syncDelay: 3000, // Delay sync 3 seconds after page load filterSettings: { iframe: { bidders: '*', // Allow all bidders filter: 'include' } } } }); ``` #### First Party Data {#first-party-data} Pass site-level or user-level first-party data to help Bidders bid more accurately: ```js pbjs.setConfig({ ortb2: { site: { name: 'My Website', domain: 'example.com', cat: ['IAB1'], // Site category content: { language: 'en' } }, user: { keywords: 'sports,news' } } }); ``` ### Testing & Debugging {#testing} **Enable Debug Mode** View the complete bidding process in the browser console: ```js pbjs.setConfig({ debug: true }); ``` You can also enable it by adding a URL parameter: ``` https://your-website.com/?pbjs_debug=true ``` **Using Prebid.js Console Methods** Use the following commands in the browser developer console to inspect the state: ```js // View all bid responses pbjs.getBidResponses(); // View all winning bids pbjs.getHighestCpmBids(); // View current configuration pbjs.getConfig(); // View Ad Units pbjs.adUnits; ``` **Using the Test Page** We provide an interactive test page [S2S Debugger](/en/adflow/s2s-debugger) that can be used to: - Verify Prebid Server connectivity - Test OpenRTB Auction requests/responses - Test Prebid.js S2S integration - View real-time bidding logs **Common Checklist** | Check Item | Description | | --- | --- | | Is Prebid.js loaded? | Run `pbjs.version` in the console to check the version | | Are Ad Units configured correctly? | Check if `pbjs.adUnits` contains your defined ad slots | | Is the Bidder responding? | Look for bid requests and responses in the Network panel | | Is GAM Targeting set? | Check if GAM request parameters include keys like `hb_pb` | | Is the S2S endpoint reachable? | Use the test page to verify Prebid Server connectivity | ### FAQ {#faq} **Q: Why am I not receiving any bids?** Common reasons: 1. `placementId` is incorrect or not activated in the AdFlow dashboard 2. Revosurge Bidder Adapter is not included in the Prebid.js build 3. Timeout is set too short (at least 2000ms recommended) 4. Network issues preventing requests from reaching the Bidder **Q: How do I configure multiple ad slots on a page?** Add an object for each ad slot in the `adUnits` array, with each object's `code` corresponding to a different `div id` on the page: ```js var adUnits = [ { code: 'top-banner', mediaTypes: { banner: { sizes: [[728, 90]] }}, bids: [{ bidder: 'revosurge', params: { placementId: 'pid-top' }}] }, { code: 'sidebar-ad', mediaTypes: { banner: { sizes: [[300, 250]] }}, bids: [{ bidder: 'revosurge', params: { placementId: 'pid-side' }}] }, { code: 'article-bottom', mediaTypes: { banner: { sizes: [[970, 250]] }}, bids: [{ bidder: 'revosurge', params: { placementId: 'pid-bottom' }}] } ]; ``` **Q: How do I improve Fill Rate?** - Add more supported ad sizes by providing additional `sizes` options - Extend the timeout appropriately - Enable User Sync to improve user identification rate - Pass first-party data to help Bidders bid more accurately **Q: Why isn't my Preferred Deal matching after configuration?** Possible reasons: 1. **Incorrect Deal ID** — Verify that the Deal ID matches exactly what was provided by the advertiser 2. **Floor price set too high** — A `bidfloor` higher than the advertiser's bid will prevent matching 3. **Deal not activated** — Contact the advertiser to confirm the deal is activated in their system 4. **Incorrect private_auction setting** — Setting it to 1 excludes open auction; recommend setting to 0 5. **Whitelist restrictions** — Check if `wseat` or `wadomain` are configured correctly ::: tip Enable Debug mode (`pbjs.setConfig({debug: true})`) to view detailed deal matching logs in the browser console. ::: --- For technical support, please contact the Revosurge technical team. --- URL: "https://docs.revosurge.com/en/adflow/s2s-debugger" LLMS_URL: "https://docs.revosurge.com/en/adflow/s2s-debugger.md" title: "S2S Debugger" description: "Test Prebid S2S config. Generate and validate bid requests for S2S integration." --- # S2S Debugger Test the Prebid.js S2S configuration approach: bid requests forwarded via Prebid Server. ## Configuration
## Code Preview Auto-generated Prebid.js S2S integration code based on your configuration above:

Generated JS Code

## Test Status

Execution Status

Prebid.js LoadingPending
S2S ConfigurationPending
Bid RequestPending
Ad RenderingPending

S2S Config

Status: Not started
## Ad Preview

Test Ad Slot (300x250)

placement-id="test-placement-1"
Waiting for auction...
## Logs
--- URL: "https://docs.revosurge.com/en/adwave/guided-campaign-setup" LLMS_URL: "https://docs.revosurge.com/en/adwave/guided-campaign-setup.md" title: "Guided campaign setup" description: "Create campaigns and creatives in AdWave. Prerequisites, validation, launch checklist." --- # Guided campaign setup **For:** UA managers, Campaign operators, Growth teams Guided Campaign Setup is a step-by-step flow to create: **Campaign → Ad (creative)** in one place, while validating prerequisites. ## In this article - Prerequisites - Step 1: Product & target event - Step 2: Campaign settings - Step 3: Creatives - Step 4: Review & publish - What to monitor after launch ## Prerequisites Before you start, ensure: - Account status is ready - Wallet has sufficient balance - At least one Product is available - Target events you need are available for selection (depends on current rollout rules) ## 1) Select Product & target event 1) Choose the **Product** you want to promote 2) Select the **Target event** (optimization goal), such as: - Register - First Time Deposit (FTD) - Deposit (if supported) Your target event is used for: - Optimization logic (where enabled) - Performance reporting and evaluation ## 2) Campaign settings (campaign-level) Set the core campaign configuration: **Campaign name** - Human-readable name used in reporting **Campaign type / Ad format** - Example: Display, Pop, Native (based on current availability) - Some formats may be locked after publish (depends on product rule) **Schedule** - Start time: now or future - End time: must be at least 24h after start (if required) **Budget** - Daily budget (USD) **Bid / target CPM** - Set your target CPM (or bid goal) used for RTB bidding strategy > Important: In some current versions, billing markup may be applied **after** bidding/reporting. Align on the billing logic with your internal owner before using pilot data for revenue conclusions. ## 3) Creatives (ad-level) Upload one or more creatives compatible with the selected ad format: - Image / HTML / etc. depending on format For each creative, configure: - Destination URL (landing page) - Format-specific fields (title, description, CTA) if required ## 4) Review & publish On the review screen: - Confirm product, event, budget, bid/CPM, targeting, and creatives Actions: - **Save Draft** (if available) - **Publish** to activate / schedule the campaign ## After launch: what to monitor (pilot checklist) **Delivery** - Impressions, Spend, CPM - Win rate (if available) - Geo mix vs expected **Engagement** - Clicks, CTR - Very high imps + near-zero clicks → investigate inventory quality **Outcomes (if connected)** - Conversions (Register/FTD) - CPA / ROAS (if available) --- URL: "https://docs.revosurge.com/en/api/api-key" LLMS_URL: "https://docs.revosurge.com/en/api/api-key.md" title: "API Key" description: "API key authentication. Security, key rotation, secrets management." --- # API Key **For:** Developers, Admins API keys authenticate requests to RevoSurge APIs. ## In this article - What an API key is - How to keep it safe - Key rotation basics ## What an API key is An API key identifies your account and authorizes API actions (e.g., sending S2S events). ## Keep it safe - Do not commit keys into source control - Store keys in environment variables or a secrets manager - Restrict access to only required engineers/services ## Rotation (recommended) - Rotate keys periodically (e.g., quarterly) - Rotate immediately if exposure is suspected --- URL: "https://docs.revosurge.com/en/api/quickstart" LLMS_URL: "https://docs.revosurge.com/en/api/quickstart.md" title: "API Quickstart" description: "API overview — S2S events, reporting, API keys, integration patterns." --- # API Quickstart **For:** Developers, Technical integrators, BI engineers RevoSurge APIs let you automate workflows and integrate reporting and events into your own systems. ## In this article - What you can do with the API - Typical integration patterns - Before you start (auth) ## What you can do with the API Common use cases include: - Send **Server-to-Server (S2S) events** - Pull reporting aggregates (imps, clicks, spend, conversions) where available - Manage keys and access (depending on console capabilities) ## Typical integration patterns - Daily export to data warehouse for reporting - Server events for deposits/transactions - Building user segments (if/when supported by API) ## Before you start You will need: - An API key (see **API Key**) - The correct base URL and endpoint reference (see **Server Events API**) --- URL: "https://docs.revosurge.com/en/audience/create-audience-segment" LLMS_URL: "https://docs.revosurge.com/en/audience/create-audience-segment.md" title: "Create an audience segment" description: "Create segments in AdWave — metadata, match type (AND/OR), rules, validation." --- # Create an audience segment (current UI) **For:** Campaign operators, Growth teams This section describes the segment creation UI currently available. ## In this article - Enter segment metadata - Choose match type - Add rules (behavioural conditions) - Run & validate - Save and use ## 1) Enter segment metadata In **AdWave → Audience**, click **Create Audience** and provide: - **Name**: Segment name displayed in the list - **Description** (optional): What the segment is for ## 2) Choose match type (AND / OR) When defining your rules, select how multiple conditions are combined: - **Match All Conditions (AND):** users must satisfy every selected rule - **Match Any Condition (OR):** users can satisfy any one of the rules ## 3) Add behavioural rules (conditions) Under **Behavioural**, select one or more conditions (based on current UI availability), such as: - **Ad Impression** — Users who saw your ad - **Ad Click** — Users who clicked your ad - **Site Visit** — Users who visited your site > If your UI supports expanding each rule (dropdown arrow), use it to select the time window or additional parameters when available. ## 4) Review the summary and estimated size The right-side **Summary** panel is used to validate: - The combined logic (AND/OR) - The estimated audience size (when the system can calculate it) Click **Run** (if shown) to generate the estimate and validate configuration. ## 5) Save the segment After saving, your segment appears in the **Audience Segments** list with: - **Type** (e.g., Behavioural) - **Source** (e.g., User Defined) - **Size** - **In Use** (how many campaigns currently reference it) - **Status** (Active / Inactive) --- URL: "https://docs.revosurge.com/en/audience/segment-details" LLMS_URL: "https://docs.revosurge.com/en/audience/segment-details.md" title: "Audience segment details" description: "Segment details — name, type, source, match type, size, status, usage." --- # Audience segment details **For:** UA managers, Operations Click a segment to view its details. Current fields include: - **Name** - **Type** (e.g., Behavioural) - **Source** (e.g., User Defined) - **Description** - **Match Type** (Match All Conditions / Match Any Condition) - **Size** - **In Use** - **Status** - **Created** timestamp --- URL: "https://docs.revosurge.com/en/audience/segments" LLMS_URL: "https://docs.revosurge.com/en/audience/segments.md" title: "Audience segments" description: "Define segments by behavior for targeting. Retarget, exclude low-quality, interest audiences." --- # Audience segments **For:** UA managers, Growth teams, Campaign operators Audience Segments let you define groups of users based on behavior signals, then use those segments for targeting campaigns. ## In this article - What an audience segment is - Where segments are used - Create a segment (based on current UI) - Segment details & fields - Notes and limitations (current version) ## What is an audience segment? An **Audience Segment** is a saved definition that groups users who match specific conditions (e.g., users who clicked an ad, visited a site, etc.). Segments are typically used to: - Retarget engaged users - Exclude low-quality users - Create interest-based or behavior-based audiences ## Where segments are used Segments can be used in campaign targeting (Step 3 in [**AdWave → Guided campaign setup**](/en/adwave/guided-campaign-setup)) when the UI allows selecting audience labels/segments. --- URL: "https://docs.revosurge.com/en/growth/account" LLMS_URL: "https://docs.revosurge.com/en/growth/account.md" title: "Creating your RevoSurge account" sidebar_label: "Creating your account" description: "Create or activate account. Company identity, billing, users, products." --- # Creating your RevoSurge account **Audience:** Admin / Master users, account owners, operations ## What is a RevoSurge account? A RevoSurge account represents your business on the platform. It is the container for: - Legal company identity - Billing and funding (shared wallet for AdWave and DataPulse) - Users, roles, and permissions - Products (websites/apps) you want to promote - Campaigns, analytics, and financial balances ## Prerequisites Prepare: - Legal company name - Registered business address and country - Main contact name and email - Optional billing contact (recommended) ## Create or activate your account 1. **Sign up or accept an invite** - Use the sign-up link from your RevoSurge representative, or - Accept the invitation email if your company account already exists. 2. **Fill in company details** - Company legal name - Country of registration - Business address - Primary contact (name + email) 3. **Accept the online agreement** Your click-to-accept acts as a digital signature. When accepted, account status becomes eligible to be **Ready** (if mandatory details are complete). ## Add team members and roles Built-in roles: - **Admin (Master)**: full access (including user/role management) - **Ad Executive**: manage products, campaigns, creatives, and reports (assigned scope) - **Data Analytic**: manage data assets and view campaigns/reports (assigned scope) - **Finance**: view balances, invoices, and financial reporting How to invite: 1. Go to **Account → Members** 2. Click **Invite member** 3. Enter email + role + optional message 4. Click **Send invite** Notes: - You can change roles, disable users, or resend invites later. - Keep at least **one Admin/Master** in every account (the last Admin cannot be removed). --- URL: "https://docs.revosurge.com/en/growth/funding-wallet" LLMS_URL: "https://docs.revosurge.com/en/growth/funding-wallet.md" title: "Funding your shared wallet" sidebar_label: "Funding & wallet" description: "Deposit to shared wallet. Payment methods, verification, transaction records." --- # Funding your shared wallet **Audience:** Admin/Master, Finance ## Shared wallet concept AdWave and DataPulse share the same **account-level wallet**. You deposit once and use the same balance across services. ## Deposit funds 1. Go to **Billing → Deposit funds** 2. Choose a payment method (availability depends on region), such as: - Credit card - Bank transfer - Crypto wallet 3. Enter the deposit amount (respect any minimum deposit requirement) 4. Confirm any **non-refundable** disclaimer (if shown) 5. Complete the payment flow ## Verify deposit success After payment: - Your **Account balance** should update - A **Deposit** record should appear in **Transaction history** ## Recommended operational practice - Finance reviews wallet balance daily - If campaigns are planned, keep buffer balance to avoid delivery pauses due to insufficient funds --- URL: "https://docs.revosurge.com/en/growth/getting-started" LLMS_URL: "https://docs.revosurge.com/en/growth/getting-started.md" title: "Getting started" description: "Account setup, funding, product config, launching first campaign." --- # Getting started **For:** Account owners, Admins, Operations, UA managers, Finance ## In this article - Account structure & roles - Funding & billing basics - Product setup (high-level) - Launching your first pilot - What to measure in the first 72 hours ## 1) Account structure & roles A RevoSurge account represents your business on the platform. It includes: - Company identity (legal name, region) - Users, roles, and permissions - Billing and wallet balance - Products (websites/apps) - Campaigns and reporting **Common roles (example):** - **Admin / Master:** Full access, user management, billing visibility - **Ad Executive:** Campaign and creative management - **Data Analyst:** Reporting and measurement (where available) - **Finance:** Balance, invoices, transaction records > Tip: Keep at least one Admin/Master user active to avoid access lockouts. ## 2) Funding & wallet basics RevoSurge uses an **account-level shared wallet**. Before running campaigns, confirm: - Wallet has enough balance for planned spend - Your finance team understands deposit flow and transaction records What you should be able to see: - Current balance (wallet) - Transaction history / deposit records - Campaign spend totals (in AdWave) ## 3) Product setup (high-level) A **Product** is the site/app you promote. At minimum you need: - A product selected in AdWave - Tracking readiness (see [**Tracking → Overview**](/en/tracking/overview)) ## 4) Launching your first pilot (recommended checklist) Before going live: - ✅ Product selected - ✅ Target event selected (must be available/live depending on current rules) - ✅ Creative uploaded & reviewed - ✅ Geo targeting set - ✅ Daily budget & CPM/bid set - ✅ Monitoring plan agreed (who reviews spend, performance, quality) ## 5) What to measure in the first 72 hours **Client-side effectiveness (advertiser view):** - Impressions, Clicks, CTR - Landing sessions / visits (if measured) - Conversions (if available) - Spend, CPM, CPC, CPA (if applicable) **Ops & unit economics (platform view):** - Spend distribution by SSP / publisher - Win rate, clearing eCPM distribution - Media cost vs client billed spend (markup realization) - Inventory quality signals (e.g., "high imps / no clicks" outliers) --- URL: "https://docs.revosurge.com/en/reference-data/exchange-rates" LLMS_URL: "https://docs.revosurge.com/en/reference-data/exchange-rates.md" title: "Exchange Rate Reference" description: "Browse monthly exchange-rate reference data by month." --- # Exchange Rate Reference Monthly exchange-rate reference data published from the internal finance pipeline. --- URL: "https://docs.revosurge.com/en/revosurge/welcome" LLMS_URL: "https://docs.revosurge.com/en/revosurge/welcome.md" title: "RevoSurge Overview" sidebar_label: "Overview" description: "RevoSurge platform — AdWave, DataPulse, account, wallet, advertiser workflow." --- # Welcome to RevoSurge **For:** Advertisers, Growth teams, UA managers, Operations, Finance, Developers RevoSurge helps advertisers run programmatic acquisition with **AdWave (DSP)** and understand outcomes with **DataPulse (Analytics)** — all under **one account**, **one wallet**, and **one set of products**. This guide covers: - How your RevoSurge account is structured - How to fund and manage access - How to launch campaigns in AdWave (guided setup) - What metrics to monitor during a pilot - API quickstart (high-level, non-technical) ## In this article - What RevoSurge includes - Key concepts (Account / Wallet / Product) - Typical workflow - Where to go next ## What RevoSurge includes - **AdWave (DSP):** Create and run campaigns across multiple SSPs via RTB. - **DataPulse (Analytics):** View downstream outcomes and reporting (availability depends on your current rollout). - **Tracking:** Web tracker and Server-to-Server (S2S) events to connect ad exposure to onsite/onsystem outcomes. ## Key concepts - **Account:** Your company container in RevoSurge (users, billing, products, campaigns). - **Wallet:** Shared balance used by AdWave and (when enabled) DataPulse-related services. - **Product:** A website/app destination you promote. Campaigns run against a selected product. - **Event:** A tracked action you want to optimize/measure (e.g., Register, Deposit). ## Typical workflow 1) Create/activate an account and add teammates 2) Create a product (site/app) 3) Ensure tracking is ready (Web tracker / S2S events) 4) Create a campaign in AdWave (guided setup) 5) Monitor pilot performance & traffic quality 6) Scale budgets, refine targeting, and apply kill rules where needed ## Where to go next - If you're new: start in [**Growth → Getting started**](/en/growth/getting-started) - If you're integrating tracking: go to [**Tracking → Overview**](/en/tracking/overview) - If you're launching ads: go to [**AdWave → Guided campaign setup**](/en/adwave/guided-campaign-setup) - If you need audience targeting: go to [**Audience**](/en/audience/segments) - If you're building integrations: go to [**API → API quickstart**](/en/api/quickstart) --- URL: "https://docs.revosurge.com/en/supply/bid-endpoint" LLMS_URL: "https://docs.revosurge.com/en/supply/bid-endpoint.md" title: "Bid Endpoint Reference" description: "OpenRTB 2.5 bid request and response field reference for RevoSurge RTB integration." --- # Bid Endpoint Reference ## Endpoint | | | |---|---| | **URL** | `http://rtb.revosurge.com/api/v1/openrtb2/{sspId}/bid` | | **Method** | `POST` | | **Content-Type** | `application/json` | | **Protocol** | OpenRTB 2.5 | ## Bid Request ### Top-level fields | Field | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Unique ID for this bid request | | `imp` | array | Yes | List of impression objects (see below) | | `site` | object | Recommended | Site where the ad will appear | | `device` | object | Recommended | Device and user environment | | `user` | object | No | User identity | | `at` | integer | No | Auction type. We support `1` (first-price) | | `tmax` | integer | No | Maximum response timeout in milliseconds (e.g. `250`) | | `cur` | array | No | Allowed currencies (e.g. `["USD"]`) | | `allimps` | integer | No | Indicator of available impressions | ### Impression object (`imp[]`) | Field | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Unique impression ID | | `banner` | object | One of | Banner ad slot (see below) | | `native` | object | One of | Native ad slot | | `bidfloor` | float | No | Minimum bid price in CPM (USD). Defaults to `0` | | `bidfloorcur` | string | No | Currency for bid floor. Defaults to `USD` | | `instl` | integer | No | Set to `1` for popunder (fullscreen/interstitial) | | `tagid` | string | No | SSP zone/tag ID for the impression | | `ext.type` | string | No | Format hint from SSP. Use `"pop"` to signal popunder | ### Banner object (`imp[].banner`) | Field | Type | Description | |---|---|---| | `w` | integer | Width in pixels | | `h` | integer | Height in pixels | ### Site object (`site`) | Field | Type | Description | |---|---|---| | `id` | string | Site ID on your platform | | `name` | string | Human-readable site name | | `domain` | string | Site domain | | `page` | string | Full URL of the page | | `cat` | array | IAB content categories | | `publisher.id` | string | Publisher ID | | `keywords` | string | Comma-separated keywords | ### Device object (`device`) | Field | Type | Description | |---|---|---| | `ua` | string | User agent string | | `ip` | string | IPv4 address of the user | | `ipv6` | string | IPv6 address of the user (send if no IPv4 is available) | | `geo.country` | string | ISO 3166-1 alpha-3 country code (e.g., `IND`, `IDN`, `USA`) | | `os` | string | Operating system (e.g., `Android`, `iOS`) | | `devicetype` | integer | OpenRTB device type code (e.g., `1` = mobile) | | `language` | string | Browser/device language code | | `carrier` | string | Mobile carrier name | | `js` | integer | `1` if JavaScript is supported, `0` otherwise | ### User object (`user`) | Field | Type | Description | |---|---|---| | `id` | string | Buyer-specific user ID | --- ## Bid Response On a successful bid, we return HTTP `200` with a JSON body. If we have no matching campaign, we return HTTP `204 No Content` (no body). ### Top-level fields | Field | Type | Description | |---|---|---| | `id` | string | Echoes the bid request `id` | | `seatbid` | array | Array with one seat bid object | | `cur` | string | Currency — always `USD` | ### Bid object (`seatbid[].bid[]`) | Field | Type | Description | |---|---|---| | `id` | string | Unique bid ID | | `impid` | string | Impression ID from the request | | `price` | float | Bid price in CPM (USD) | | `adid` | string | Campaign ID | | `crid` | string | Creative ID | | `adm` | string | Ad markup — HTML for banner/native; redirect URL for popunder | | `ext.popurl` | string | Popunder landing URL (popunder only, mirrors `adm`) | | `w` | integer | Creative width (`0` for popunder) | | `h` | integer | Creative height (`0` for popunder) | | `nurl` | string | Win notification URL (fire when we win) | | `burl` | string | Billing notification URL (fire on impression) | | `lurl` | string | Loss notification URL with `${AUCTION_LOSS}` macro (fire when we lose) | --- ## Example ### Request ```json { "id": "xqoErTidWX", "imp": [ { "id": "AhpTG", "banner": { "w": 300, "h": 250 }, "bidfloor": 0 } ], "site": { "id": "674721464", "domain": "example.com", "page": "https://example.com", "cat": ["IAB25-3"], "publisher": { "id": "17918" } }, "device": { "ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36", "geo": { "country": "IND" }, "ip": "223.184.195.38", "os": "Android", "language": "en" }, "user": { "id": "platform:2fda85882b825efbb54e84d014ff8fb9" }, "at": 1 } ``` ### Response (bid) ```json { "id": "xqoErTidWX", "seatbid": [ { "bid": [ { "id": "xqoErTidWX", "impid": "AhpTG", "price": 0.5, "adid": "AWC-20251003-094732-029-6102", "crid": "AWC-20251003-094732-029-6102", "adm": "", "w": 300, "h": 250, "nurl": "http://rtb.revosurge.com/rtb/win?id=xqoErTidWX&impId=AhpTG", "burl": "http://rtb.revosurge.com/rtb/bill?id=xqoErTidWX&impId=AhpTG", "lurl": "http://rtb.revosurge.com/rtb/loss?id=xqoErTidWX&impId=AhpTG&nbr=${AUCTION_LOSS}" } ], "seat": "revo" } ], "cur": "USD" } ``` ### Response (no bid) ``` HTTP 204 No Content ``` --- ## Popunder format To request popunder inventory, set `imp[].instl: 1` and `imp[].ext.type: "pop"`. The response `adm` will be a redirect URL (not HTML), and the bid will also include `ext.popurl` with the same value. ### Request (popunder) ```json { "id": "pxBrQtYuWZ", "imp": [ { "id": "ImpPop1", "instl": 1, "bidfloor": 0.1, "ext": { "type": "pop" } } ], "site": { "id": "70915", "domain": "example.com", "page": "https://example.com/", "ext": { "categories": "Entertainment" } }, "device": { "ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36", "geo": { "country": "VNM" }, "ip": "113.175.11.125", "os": "Android" }, "at": 1, "tmax": 250 } ``` ### Response (popunder bid) ```json { "id": "pxBrQtYuWZ", "seatbid": [ { "bid": [ { "id": "b91c3e2a-7f4d-4b1a-93ec-8f21ad047c12", "impid": "ImpPop1", "price": 0.64, "adid": "AWA-20260403-060030-100-5550", "crid": "AWR-20260326-024959-045-0754", "adm": "https://ingestor.revosurge.com/pop?...", "ext": { "popurl": "https://ingestor.revosurge.com/pop?..." }, "w": 0, "h": 0, "nurl": "http://rtb.revosurge.com/rtb/win?id=pxBrQtYuWZ&impId=ImpPop1", "burl": "http://rtb.revosurge.com/rtb/bill?id=pxBrQtYuWZ&impId=ImpPop1", "lurl": "http://rtb.revosurge.com/rtb/loss?id=pxBrQtYuWZ&impId=ImpPop1&nbr=${AUCTION_LOSS}" } ], "seat": "revo" } ], "cur": "USD" } ``` --- URL: "https://docs.revosurge.com/en/supply/getting-started" LLMS_URL: "https://docs.revosurge.com/en/supply/getting-started.md" title: "Getting Started — SSP Integration" description: "Step-by-step guide to onboarding RevoSurge as a DSP buyer on your SSP." --- # Getting Started This guide walks you through connecting RevoSurge as a buyer on your SSP. ## Step 1 — Request an SSP ID Contact the RevoSurge partnerships team to receive your assigned `sspId`. This ID is used in the bid endpoint URL and allows us to route traffic and track performance per SSP. ## Step 2 — Configure your endpoint Point your OpenRTB traffic to: ``` POST http://rtb.revosurge.com/api/v1/openrtb2/{sspId}/bid Content-Type: application/json ``` Replace `{sspId}` with the ID provided to you. ## Step 3 — Send a test request Send a minimal bid request to verify connectivity: ```bash curl -X POST http://rtb.revosurge.com/api/v1/openrtb2/{sspId}/bid \ -H "Content-Type: application/json" \ -d '{ "id": "test-001", "imp": [{ "id": "1", "banner": { "w": 300, "h": 250 }, "bidfloor": 0 }], "site": { "domain": "example.com", "page": "https://example.com" }, "device": { "ua": "Mozilla/5.0", "ip": "1.2.3.4", "geo": { "country": "IND" } }, "at": 1 }' ``` **Expected responses:** - `200 OK` with a bid response body — we placed a bid - `204 No Content` — no matching campaign for this request (no action needed) ## Step 4 — Verify notification URLs Ensure your SSP fires the notification URLs returned in our bid response: | URL field | When to fire | Macro to substitute | |---|---|---| | `nurl` (win URL) | Immediately when your SSP determines RevoSurge won the auction | none | | `burl` (billing URL) | When the impression is rendered / billed | none | | `lurl` (loss URL) | When RevoSurge loses the auction (optional but recommended) | `${AUCTION_LOSS}` → loss reason code | See [Notifications](/en/supply/notifications) for details. ## Step 5 — Go live checklist - [ ] SSP ID received and configured in endpoint URL - [ ] `Content-Type: application/json` header set on all requests - [ ] Test request returns 200 or 204 (no error responses) - [ ] Win notification (`nurl`) firing confirmed - [ ] Billing notification (`burl`) firing confirmed - [ ] Bid request includes `device.geo.country`, `device.ua`, `device.ip` --- URL: "https://docs.revosurge.com/en/supply/notifications" LLMS_URL: "https://docs.revosurge.com/en/supply/notifications.md" title: "Notifications" description: "Win, billing, and loss notification handling for RevoSurge RTB integration." --- # Notifications When RevoSurge bids, we include three notification URLs in the bid response. Your SSP is responsible for firing these URLs at the right time with the correct macro values substituted. ## Notification URLs | Field | Fires when | Required | |---|---|---| | `nurl` (win) | Your SSP determines RevoSurge won the auction | Yes | | `burl` (billing) | The impression is rendered and billed | Yes | | `lurl` (loss) | RevoSurge loses the auction | Recommended | ## Macro substitution Only the **loss URL** (`lurl`) contains a macro that your SSP must substitute. Win and billing URLs do not include a price macro — they only carry the auction and impression IDs. | URL | Macro | Required | |---|---|---| | `nurl` | none | — | | `burl` | none | — | | `lurl` | `${AUCTION_LOSS}` | Yes — loss reason code per OpenRTB spec | ## Example URLs (as returned in bid response) **Win notification:** ``` GET http://rtb.revosurge.com/rtb/win?id=xqoErTidWX&impId=AhpTG ``` **Billing notification:** ``` GET http://rtb.revosurge.com/rtb/bill?id=xqoErTidWX&impId=AhpTG ``` **Loss notification** (substitute `${AUCTION_LOSS}` before firing): ``` GET http://rtb.revosurge.com/rtb/loss?id=xqoErTidWX&impId=AhpTG&nbr=100 ``` ## Important notes - All notification URLs use **HTTP GET** - We expect a `200 OK` response; we do not retry on failure - Loss reason codes follow the [OpenRTB 2.5 loss reason codes](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/OpenRTB%20v2.5%20FINAL.pdf) --- URL: "https://docs.revosurge.com/en/supply/overview" LLMS_URL: "https://docs.revosurge.com/en/supply/overview.md" title: "Supply Integration Overview" description: "Overview of RevoSurge RTB demand — supported formats, geo, and how SSP integration works." --- # Supply Integration Overview **Audience:** SSP engineers and partnership teams looking to connect RevoSurge as a DSP buyer. RevoSurge is a Demand-Side Platform (DSP) that bids on ad inventory via Real-Time Bidding (RTB). SSPs can connect RevoSurge as a buyer by pointing their OpenRTB traffic to our bid endpoint. ## What we buy | Dimension | Details | |---|---| | **Protocol** | OpenRTB 2.5 | | **Ad formats** | Banner, Native, Popunder | | **Auction type** | First-price (`at: 1`) | | **Currency** | USD | | **Geographic focus** | Global — Asia, US, EU regions active | ## How it works 1. Your SSP sends an OpenRTB 2.5 bid request to our endpoint via HTTP POST 2. RevoSurge evaluates the request against active campaigns (targeting, budget, bid floor) 3. We return a bid response with price, ad markup, and notification URLs — or HTTP 204 if we don't bid 4. Your SSP runs the auction; if we win, it fires our win notification URL 5. On impression, it fires our billing URL ## Endpoint ``` POST http://rtb.revosurge.com/api/v1/openrtb2/{sspId}/bid ``` Your `sspId` is assigned during onboarding. See [Getting Started](/en/supply/getting-started) for details. ## Regions Our endpoint uses dynamic DNS and automatically resolves to our nearest server across Asia, US, and EU regions — no regional configuration needed on your side. ## Next steps - [Getting Started](/en/supply/getting-started) — onboarding steps and test checklist - [Bid Endpoint Reference](/en/supply/bid-endpoint) — full request/response field spec - [Notifications](/en/supply/notifications) — win, billing, and loss notification handling --- URL: "https://docs.revosurge.com/en/tracking/overview" LLMS_URL: "https://docs.revosurge.com/en/tracking/overview.md" title: "Tracking overview" description: "Web tracker vs S2S — when to use, attribution, how tracking connects to outcomes." --- # Tracking overview **For:** Developers, Tracking/BI engineers, UA managers (technical) Tracking connects advertising delivery to measurable outcomes. In RevoSurge, there are two main ways to send events: - **Web tracker (browser-side)** - **Server-to-Server (S2S) events (backend-side)** ## In this article - What tracking is used for - Web tracker vs S2S (when to use which) - Event basics - Where tracking shows up in the product ## What tracking is used for Tracking enables: - Conversion measurement (e.g., Register, Deposit) - Attribution (tying outcomes to campaigns) - Optimization toward target events (where enabled) - Audience building (segments) based on behavior and outcomes ## Web tracker vs S2S (when to use which) **Web tracker** is best when: - You can instrument the website - You want immediate onsite signals (page views, form submits, etc.) **S2S events** are best when: - Conversions happen on backend (deposits, orders, account state changes) - You need reliable revenue and transaction data - You want to avoid client-side blockers > Many advertisers use **both**: Web tracker for onsite behavior + S2S for revenue-grade events. ## Event basics (shared) An **Event** is a named action that can be measured and potentially optimized. Common examples: - Register - First Time Deposit (FTD) - Deposit (repeated) ## Where tracking shows up Depending on your current rollout, tracking-related views may include: - Product tracker status / readiness - Event list and event status - API endpoints and authentication (for S2S) --- URL: "https://docs.revosurge.com/en/tracking/s2s/overview" LLMS_URL: "https://docs.revosurge.com/en/tracking/s2s/overview.md" title: "Server-to-Server (S2S) overview" description: "Send conversion events from backend. S2S vs Web Tracker, requirements, auth." --- # Server-to-Server (S2S) overview Server-to-Server (S2S) tracking lets you send conversion events directly from your backend to RevoSurge. Use S2S when: - You want backend-confirmed events (payments settled, deposits finalized) - Client-side tracking is unreliable (ad blockers, browser limitations) - You need to include secure transactional fields (amount, currency, transaction_id) ## S2S vs Web Tracker ### Web Tracker is best for - Capturing sessions and web context (URL, referrer) - Extracting click_id / UTM on landing - Fast implementation for websites ### S2S is best for - Confirmed conversions and financial outcomes - Higher data integrity for revenue-related events - Environments where client-side scripts are restricted > Many advertisers use both: Web Tracker for attribution context, S2S for "source of truth" conversion events. ## What S2S requires - A server integration that can call RevoSurge endpoints - Authentication (API key/token depending on your environment) - A consistent user identifier strategy (e.g., user_id) --- URL: "https://docs.revosurge.com/en/tracking/s2s/server-events-api" LLMS_URL: "https://docs.revosurge.com/en/tracking/s2s/server-events-api.md" title: "RevoSurge Server Events API" sidebar_label: "Server Events API" description: "S2S events to DataPulse. API reference, auth, single/batch ingest." --- # RevoSurge Server Events API **Audience:** Engineers, technical integrators, Admin teams ## Overview The Server Events API allows partners to securely send user events and user activities directly from their servers to the DataPulse platform. This API is designed for high-throughput scenarios and requires strict authentication via API Keys. ## Base URL | Environment | Base URL | |-------------|----------| | Production | `https://datapulse-api.revosurge.com/` | ## Authentication All requests to the Server Events API must include an API Key in the request header `X-API-Key`. #### Required Headers | Header Name | Description | |-------------|-------------| | `X-API-Key` | API Key for authentication | ## Ingestion Endpoints #### 1. Single Ingest Event | Path | Method | Content-Type | |-------- |--------|----------| | `/v2/s2s/event` | POST | `application/json` | #### 1.1 Request Body Schema The request body accepts a JSON object with the following fields: | Field | Type | Required | Description | |-------------|----------|-------------|-------------| | `client_user_id` | String | Yes | Unique identifier of the user in your system. | | `click_id` | String | Yes | Unique ID for the ad click.
**Suggested**. | | `event_name` | String | Yes | Name of the event (e.g., "register", "login", "deposit"). | | `timestamp` | Integer | Yes | Unix timestamp (in seconds) when the event occurred. | | `ip_address` | String | Yes | IP address of the user (IPv4/IPv6). | | `user_agent` | String | No | User agent string of the browser or device. | | `game_type` | String | No | Type of the game (e.g., "slot", "casino"). | | `game_provider` | String | No | Provider of the game (e.g., "EA", "GGP"). | | `transaction_id` | String | *Yes** | Unique ID for the transaction (e.g., purchase ID). | | `amount` | Float | *Yes** | Monetary value of the transaction (e.g., deposit amount). | | `currency` | String | *Yes** | 3-letter ISO currency code (e.g., USD, EUR) for fiat currency, or any specific code for crypto. | | `is_crypto` | Boolean | No | Set to `true` if the transaction is crypto-based, otherwise `false`. | | `<>` | String | No | Additional custom properties as key-value pairs. | *PS: The `transaction_id`, `amount`, `currency` is not required in non-financial events (eg. login).* #### 1.2 Example Request (curl) ```bash curl -X POST "https://<>/v2/s2s/event" -H "Content-Type: application/json" -H "X-API-KEY: dp_test_key_123" -d '{ "client_user_id": "user_001", "click_id": "clk_998877", "ip_address": "203.0.113.1", "event_name":"deposit", "transaction_id": "tx_554433", "timestamp": 1702963200, "amount": 50.00, "currency": "USD" }' ``` #### 2. Batch Ingest Event | Path | Method | Content-Type | |-------- |--------|----------| | `/v2/s2s/batch` | POST | `application/json` | #### 2.1 Request Body Schema The request body accepts a JSON object of array type. The array item is referenced as defined in section 1.1. ## Responses | Status Code | Description | |-------------|-------------| | 200 OK | Event successfully queued for processing | | 400 Bad Request | Missing required fields | | 401 Unauthorized | Invalid API Key or missing auth headers | | 429 Too Many Requests | Rate limit exceeded | | 500 Server Error | Internal processing error. Please retry with backoff | ## Rate Limit * Limits are applied per X-API-KEY. * Standard Limit: 60 requests per minute (Default). * If you exceed the limit, you will receive a 429 response. * Retry Strategy: We recommend implementing an exponential backoff strategy when encountering 429 or 500 errors. ## Use Case Scenarios on Request Body Schema #### User Register ``` JSON { "client_user_id": "<>", "click_id": "<>", "event_name": "register", "timestamp": UTC milliseconds, "ip_address": "<>", "user_agent": "<>" } ``` #### User Login ``` JSON { "client_user_id": "<>", "click_id": "<>", "event_name": "login", "timestamp": UTC milliseconds, "ip_address": "<>", "user_agent": "<>" } ``` #### User Deposit ``` JSON { "client_user_id": "<>", "click_id": "<>", "event_name": "deposit", "currency": "<>", "amount": 5.00, "transaction_id": "<>", "timestamp": UTC milliseconds, "ip_address": "<>", "is_crypto": true | false } ``` #### User Bet ``` JSON { "client_user_id": "<>", "event_name": "bet", "game_type": "<>", "game_provider": "<>", "currency": "<>", "amount": 5.00, "transaction_id": "<>", "timestamp": UTC milliseconds, "is_crypto": true | false, "bet_result": "win | loss", "bet_result_amount": 1.00 } ``` #### User Win/Loss ``` JSON { "client_user_id": "<>", "event_name": "win | loss", "game_type": "<>", "game_provider": "<>", "currency": "<>", "amount": 5.00, "transaction_id": "<>", "parent_transaction_id": "<>" "timestamp": UTC milliseconds, "is_crypto": true | false } ``` *PS: Could also be sent within `bet` event using `bet_result` and `bet_result_amount` field.* #### User Withdraw ``` JSON { "client_user_id": "<>", "event_name": "withdraw", "currency": "<>", "amount": 5.00, "transaction_id": "<>", "timestamp": UTC milliseconds, "ip_address": "<>", "is_crypto": true | false } ``` --- URL: "https://docs.revosurge.com/en/tracking/web-tracker" LLMS_URL: "https://docs.revosurge.com/en/tracking/web-tracker.md" title: "Web Tracker" description: "Tracking layer connecting AdWave to on-site outcomes. Attribution, click IDs, UTM, events." --- # Tracking overview RevoSurge Tracking is the data collection and attribution layer that connects: - **AdWave delivery** (impressions / clicks / spend) - **Your on-site outcomes** (registrations, deposits, first-time deposits, etc.) - **DataPulse reporting** (performance and ROI, when enabled) This section explains: - Why tracking is required - How attribution works at a high level (click IDs / UTM) - How events are linked across systems (Web Tracker + S2S) ## Why tracking matters Tracking enables RevoSurge to: - Attribute conversions back to campaigns, ad groups, creatives, and sources - Optimize bidding toward business outcomes (e.g., Register / Deposit / FTD) - Produce consistent reporting across AdWave and DataPulse Without tracking, you can still buy traffic, but you **cannot** reliably measure or optimize toward outcomes. ## Attribution basics (click IDs & UTM) RevoSurge associates user sessions and conversions using identifiers captured at the time of the visit. Common identifiers: - **click_id** (e.g., `gclid`, `fbclid`, or a platform click id) - **UTM parameters** (e.g., `utm_source`, `utm_campaign`, etc.) For AdWave-delivered traffic, required parameters are captured automatically. For non-AdWave traffic, you may need to ensure tracking parameters are present in destination URLs. ## How events are linked RevoSurge supports two complementary event sources: ### 1) Web Tracker (client-side) Best for web products where you can add a script to the website and fire events in the browser. - Captures sessions and web context (URL, referrer, etc.) - Can automatically extract click_id / UTM from landing page URLs ### 2) Server-to-Server (S2S) Best for backend-confirmed events (e.g., payment confirmed, deposit settled), or when client-side tracking is limited. - You send events directly from your server to RevoSurge - Supports financial values and (when available) crypto-to-fiat conversion logic > Recommendation: Use Web Tracker for session attribution + S2S for "source of truth" financial events when possible. ## What you will set up - A **Product** in RevoSurge (the container for tracking + campaigns) - A **Tracking method** (Web Tracker and/or S2S) - A set of **standard events** (e.g., Register, Deposit, FirstTimeDeposit) --- URL: "https://docs.revosurge.com/en/tracking/web-tracker/events" LLMS_URL: "https://docs.revosurge.com/en/tracking/web-tracker/events.md" title: "User Events and Activities" sidebar_label: "Events" description: "User events — Register, FTD, Deposit, Login. Status and best practices." --- # User Events and Activities User Events are business actions that RevoSurge tracks and aggregates. They are used for analytics and (when supported) optimization targets in AdWave. ## Common event examples - Register - FirstTimeDeposit (FTD) - Deposit / Purchase - Login - Custom events ## Event status Each event can have a status indicating whether it is reliable and recent enough: - **Live**: event is receiving data and can be used in campaign flows where Live is required - **Inactive / Not ready**: insufficient or no recent event data ## Best practice For performance campaigns, always validate at least: - Register - Deposit / FTD (if your business model uses deposit as primary conversion) --- URL: "https://docs.revosurge.com/en/tracking/web-tracker/install" LLMS_URL: "https://docs.revosurge.com/en/tracking/web-tracker/install.md" title: "Instal the Web Tracker" sidebar_label: "Instal the Web Tracker" description: "Install Web Tracker — create product, add script, configure events." --- # Instal the Web Tracker **Audience:** Developers, tracking engineers, BI/analytics owners ## Before you start Make sure you have: - A RevoSurge account with access to Product management - A Product created for your website domain - Access to your website codebase or tag manager - A list of key events to track (e.g., Register, FirstTimeDeposit, Deposit) ## Step 1 — Create a Product (domain) 1. Go to **Product management → Products** 2. Click **Create product** 3. Enter your website domain (e.g., `www.example.com`) 4. Save This creates the Product and assigns a **Tracker ID**. ## Step 2 — Install tracker code (Example / Draft) > **Example / Draft (subject to change)** > Use the tracker snippet provided in your product's tracking settings. ```html ``` ## Step 3 — Initialize tracker (Example / Draft) ```js const tracker = new WebTracker({ trackerId: "your-tracker-id", // env: "prod" | "test" | "dev" }); ``` ## Step 4 — Send key events (Example / Draft) ```js tracker.trackRegister("user_123", { identifier: "hashed_email_or_phone" }); tracker.trackDeposit("user_123", { currency: "USDT", network: "TRON", amount: 100 }); ``` ## Step 5 — Verify tracker & event status Go to your tracking/status page and verify: - **Tracker status** - Active / In-use: events are flowing - Inactive: no recent data received - **Event status** - Live: can be used as campaign optimization target - Inactive / Not ready: insufficient or no recent event data Once key events are Live, your Product is ready for AdWave campaigns. --- URL: "https://docs.revosurge.com/en/tracking/web-tracker/reference" LLMS_URL: "https://docs.revosurge.com/en/tracking/web-tracker/reference.md" title: "Web Tracker SDK Reference" description: "Web Tracker SDK — trackRegister, trackDeposit, trackEnterGame, event methods." --- # Web Tracker SDK Reference Use these reference after the SDK is loaded and initialized. Start with registration, then track downstream actions in the order they occur for clearer attribution. ## Event reporting APIs ### trackRegister Bind the first unique user identifier; all later events attach to this account. ```js tracker.trackRegister('user_123', { identifier: 'hashed_email_or_phone' }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | user_id | string | Yes | Unique user ID. | | identifier | string | No | Hashed email or phone for de-duplication. | ### trackDeposit Record money moving in for conversion and risk analysis. ```js tracker.trackDeposit('user_123', { currency: 'USDT', network: 'TRON', amount: 100 }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | user_id | string | Yes | Unique user ID. | | currency | string | Yes | Currency code, e.g., `USDT`. | | network | string | Yes | Payment rail or chain, e.g., `TRON`. | | amount | number | Yes | Amount value. | ### trackEnterGame Capture when the user starts the core experience (game or key flow). ```js tracker.trackEnterGame('user_123', { currency: 'USDT', game_provider: 'provider_xyz', game_id: 'gamer_123', game_name: 'My Awesome Game' }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | user_id | string | Yes | Unique user ID. | | currency | string | Yes | Selected denomination. | | game_provider | string | Yes | Provider or partner name. | | game_id | string | Yes | Internal game or feature ID. | | game_name | string | Yes | Game or experience display name. | ### trackLogin Confirm returning users and continue the same account session. ```js tracker.trackLogin('user_123'); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | user_id | string | Yes | Unique user ID. | ### trackDownloadClick Mark when a user triggers a download or store jump from the page. ```js tracker.trackDownloadClick('user_123', { store_type: 'App Store' }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | user_id | string | No | Unique user ID. | | store_type | string | No | Channel of the download, e.g., App Store or Play Store. | ### trackCustomEvent Add business-specific events such as mission complete or item purchase. ```js tracker.trackCustomEvent('custom_event_type', { event_detail: 'value' }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | event_type | string | Yes | Custom event name. | | payload | object | No | Key-value payload for the event. | ## Utility reference ### getClickid() Returns the stored `clickid` from UTM data. If the URL contains `?clickid=...`, the SDK extracts and saves it automatically. ```js const clickid = tracker.getClickid(); if (clickid) { console.log('Click ID:', clickid); } ``` Returns: `string | null` ### getVersion() Returns the current SDK version string. ```js const version = tracker.getVersion(); console.log('SDK Version:', version); ``` Returns: `string` --- URL: "https://docs.revosurge.com/README" LLMS_URL: "https://docs.revosurge.com/README.md" --- # revo-docs Documentation site powered by **VitePress** (Vue 3). ## How to run (npm only) ```bash npm i npm run dev ``` `pnpm` will cause issues here — **use npm**. ## Deploy / branching - **Push directly to `main`** (this repo is an exception; no PR / third-party merge required). - `main` is deployed to **`docs.revosurge.com`** via **GitHub Workflows**. ## Development guidelines (keep it simple) - **Docs live in Markdown**: add/edit pages under `en/`, `cn/`, `hk/` (example: `en/tracking/`, `en/growth/`, `en/api/`, `en/adwave/`). - **English is the source of truth**: 简/繁 (`cn/`, `hk/`) are **AI-generated translations** and may need occasional tweaks. - **Navigation lives in VitePress config**: update nav/sidebar in `.vitepress/config/en.ts`, `.vitepress/config/cn.ts`, `.vitepress/config/hk.ts` when you add/move pages. (Ask Bobby) - **Prefer clean, stable paths**: avoid renaming/moving pages unless necessary; keep links relative. - **Keep pages concise**: lead with the “how”, include copy-pastable snippets, and avoid long essays. ## How to edit on GitHub Use this for **small edits to a single page** (typos, wording updates, adding a paragraph). - **Find the file** under `en/`, `cn/`, or `hk/`, then click the `.md` file you want to change. - Click the **pencil icon (Edit)**. - Make your changes in the editor. - Click **Commit changes…** - **Commit message**: write a short description (example: “Fix typo on API Quickstart”). - **Branch**: select **Commit directly to the `main` branch**. - Click **Commit changes**. Your update will publish automatically after the site rebuilds, which typically happen within 1 minute. If your change involves more complex tasks such as **adding/moving pages**, **navigation/sidebars**, or anything that feels unclear, **ask Bobby**. ## OG images (social sharing previews) Per-page Open Graph images are generated at build time. Run manually before deploying: ```bash npm run generate:og ``` This creates `public/og/{locale}/{path}.png` for each page. Commit the generated images so they deploy with the site. Add `public/og-logo.png` or `public/logo.png` for a custom logo (otherwise “RevoSurge” text is used).