Server-to-Server - Integration Guide

Server-to-Server - Integration Guide

Implement Singular's REST API for complete server-side tracking as an alternative to SDK integration, enabling full control over data collection, transmission, and attribution workflows.


Overview

Server-to-Server Use Case

Server-to-server (S2S) integration provides REST API endpoints for building complete attribution and analytics solutions running from your backend infrastructure without embedding Singular SDK in client applications.

Integration Approaches:

  • Pure S2S: 100% server-side implementation handling both session and event tracking
  • Hybrid: Singular SDK manages sessions while server-side handles event tracking

Hybrid Integration Pattern

Hybrid integration combines Singular SDK for session management with server-side EVENT API for backend event tracking, balancing ease of implementation with server-side flexibility.

Hybrid Benefits:

  • SDK handles complex session logic, deep linking, and device data collection automatically
  • Server sends events for transactions processed in backend systems
  • Reduced client-side implementation complexity
  • SESSION endpoint not required—SDK manages session lifecycle

Hybrid S2S Data Flow

Device Data Retrieval Methods:

  1. Client-Managed Flow: Capture required data points on client and forward to server via internal API for use with Singular EVENT endpoint
  2. Internal BI Postback: Configure Singular Internal BI postback to receive real-time JSON payload with device identifiers after install, re-engagement, or events (Setup Guide)

Device Graph Maintenance: Both methods require server-side logic to maintain device graph. When SDK detects device identifier changes, update server accordingly to ensure accurate tracking.

Implementation Resources:


Key Integration Principles

Principle Description
Flexibility Full control over data collection and transmission timing
Feature Parity Supports all SDK functionality when proper data provided
Integration Path Client → Your Server → Singular API
Real-time Processing One request at a time—no batch processing support
Sequential Flow Events must be processed chronologically
No Deduplication Singular does not deduplicate—implement server-side deduplication
Data Permanence Device-level data cannot be deleted after ingestion—validate before sending

Integration Requirements

Pure S2S integration requires comprehensive data pipeline implementation for session and event tracking.

  1. Data Collection: Collect required data points from client applications
  2. Device Graph: Forward data to server and maintain device identifier storage
  3. Session Requests: Send session notifications via SESSION API
  4. Response Handling: Process and relay Singular responses back to client app
  5. Event Requests: Forward events via EVENT API

REST API Endpoints

Singular provides two primary REST API endpoints for server-to-server session and event tracking.

Session Endpoint

Session Tracking API

SESSION endpoint notifies Singular of app open events to initialize user sessions for attribution and retention tracking.

GET https://s2s.singular.net/api/v1/launch

Complete reference: SESSION Endpoint API Reference


Event Endpoint

Event Tracking API

EVENT endpoint tracks in-app events and revenue for attribution analysis and campaign optimization.

GET https://s2s.singular.net/api/v1/evt

Complete reference: EVENT Endpoint API Reference


Implementation Phases

Successful S2S integration requires four key implementation phases executed sequentially for optimal data quality and attribution accuracy.

Phase 1: Data Collection

Required Data Points

Establish robust data collection strategy capturing all required parameters for Singular platform functionality.

All Required Parameters Mandatory: Omitting required parameters results in data discrepancies and attribution errors. No parameters are optional.

Async Function Handling: When collecting client-side data for server transmission, wait for asynchronous functions to complete and handle edge cases. Common issue causing missing data and partial attribution.

Implementation Resources:


Phase 2: Real-Time Streaming

Critical Timing Requirements

Real-time data streaming maintains attribution accuracy and enables time-sensitive features like SKAdNetwork conversion value updates.

Attribution Impact:

  • Delayed Sessions: Severely impact attribution accuracy—system requires precise temporal data for campaign association
  • SKAdNetwork Timer: Strict on-device timer window for conversion values makes real-time streaming critical. Delays cause missed conversion value updates and incomplete campaign data

Best Practices:

  • Implement server-side event listeners for app session starts
  • Forward session data immediately with all required parameters
  • Implement server-side event listeners for in-app events
  • Forward event data immediately with all required parameters
  • Use webhook architecture for reliable data transmission
  • Implement retry mechanisms for failed requests
  • Monitor data flow for quality assurance

Phase 3: Response Handling

Bidirectional Communication

Response handling bridges server-side API interactions with client-side functionality, enabling deferred deep linking and conversion value updates.

Key Response Types:

  • Deferred Deep Links: API response contains pending deep link data requiring immediate relay to app for user routing and personalization
  • Conversion Values: iOS SKAdNetwork conversion values must be promptly forwarded to app for accurate campaign measurement

Best Practices:

  • Implement response handling on server infrastructure
  • Parse and validate Singular API responses
  • Forward relevant response data to client app (essential for iOS SKAdNetwork)
  • Implement client-side response processing
  • Handle errors gracefully with proper HTTP status codes
  • Log failed responses for retry mechanisms

Phase 4: Testing & Validation

Data Flow Verification

Testing phase validates complete data pipeline functionality and attribution accuracy before production deployment.

Session Attribution Processes:

  • First Session (New Install): Singular recognizes new install and triggers install attribution process
  • Re-engagement Qualified: Singular triggers re-engagement attribution process (Re-engagement FAQ)
  • Standard Session: Singular records session for user activity and retention metrics

Critical Timing Requirements:

  1. Session Before Events: Single SESSION must be received before any events. SDK triggers session on app open, then sends in-app events. After 1+ minute background, session times out. New session sent when app returns to foreground. Use app lifecycle events and timers for session management
  2. Real-Time Events: Events occurring in app must be sent real-time after their respective session

Validation Checklist:

  • Test session data flow—validate first and subsequent sessions have correct data points and values
  • Confirm events received only after session reported to Singular (events before session create organic attribution)
  • Confirm session response handled and passed to client app (critical for deferred deep links)

Integration Complete:

  • ✓ Data collection and storage validated
  • ✓ Real-time streaming to Singular validated
  • ✓ Response handling and logging validated
  • ✓ All testing data flows validated

Testing guide: S2S Integration Testing Guide


Advanced Features

Enhance S2S integration with advanced attribution handling, deep linking, cross-device tracking, and platform-specific capabilities.

Apple Search Ads Attribution

iOS Search Ads Integration

Apple Search Ads is a Self-Attributing Network (SAN) requiring platform-specific attribution implementation via Apple frameworks.

Framework Support:

Dual Implementation: Implement both iAd and AdServices frameworks until iAd deprecated. Singular prioritizes AdServices over iAd signals for attribution and reporting.

Complete guide: Apple Search Ads Integration Documentation


iAd Framework Implementation

Retrieve and send Apple Search Ads attribution data via iAd framework for iOS 14.2 and below.

Step 1: Retrieve Attribution Data

Objective-C
#import <iAd/iAd.h>

Class ADClientClass = NSClassFromString(@"ADClient");

if (ADClientClass) {
    id sharedClient = [ADClientClass performSelector:@selector(sharedClient)];
    
    if ([sharedClient respondsToSelector:@selector(requestAttributionDetailsWithBlock:)]) {
        [sharedClient requestAttributionDetailsWithBlock:^(NSDictionary *attributionDetails, NSError *error) {
            if (attributionDetails && attributionDetails.count  0) {
                // REPORT attributionDetails FROM YOUR APP TO YOUR SERVER
            }
        }];
    }
}

Latency Handling: Users clicking Search Ads may download and open app immediately. Prevent attribution timing issues by:

  1. Setting few-second delay before retrieving attribution data
  2. Implementing retry logic if response False or error code (0, 2, 3). Retry 2 seconds later

Step 2: Send to Singular

Report event with reserved name __iAd_Attribution__ via EVENT endpoint, passing attribution JSON as e parameter.

Timing Requirements:

  • iOS 13+: Send __iAd_Attribution__ event immediately after first session post-install/reinstall. Otherwise Apple Search Ads data not considered for attribution
  • iOS 14+: Attribution responses only available under certain conditions and unavailable if ATT status is ATTrackingManager.AuthorizationStatus.denied

AdServices Framework Implementation

Retrieve and send attribution token via AdServices framework for iOS 14.3 and above.

Step 1: Retrieve Attribution Token

Objective-C
#import <AdServices/AdServices.h>

NSError *error = nil;
Class AAAttributionClass = NSClassFromString(@"AAAttribution");
if (AAAttributionClass) {
    NSString *attributionToken = [AAAttributionClass attributionTokenWithError:&error];
    if (!error && attributionToken) {
        // Handle attributionToken
    }
}

Token Characteristics:

  • Generated on device
  • Cached for 5 minutes—new token generated after expiry if attributionToken() called
  • Valid for 24 hours

Step 2: Send to Singular

URL-encode token and append to SESSION endpoint as attribution_token parameter on first session after every install and reinstall.


Google Play Install Referrer

Android Install Attribution

Google Play Install Referrer provides most accurate Android install attribution, containing information about user origin before Play Store arrival.

Required For:

More info: Google Install Referrer Documentation

Implementation Steps:

  1. Retrieve install referrer on first app open using Play Install Referrer API
  2. Report session via SESSION endpoint including install_ref JSON parameter with required attributes

install_ref Attributes:

Attribute Description
referrer Referrer value from Play Install Referrer API (JSON object—encode as string)
referrer_source Specify "service"
clickTimestampSeconds Click timestamp from API (e.g., "1550420123")
installBeginTimestampSeconds Install start time from API
current_device_time Current device time in milliseconds (e.g., "1550420454906")

Meta Install Referrer

Facebook Attribution Enhancement

As of June 18, 2025: Meta's Advanced Mobile Measurement (AMM) removes need for Meta Install Referrer implementation. Not recommended if AMM enabled.

Meta Referrer is Android-specific measurement solution providing granular user-level attribution data for app installs, combining Google Play Install Referrer and Meta Install Referrer technologies.

Learn more: Meta Referrer FAQ

Implementation Steps:

  1. Retrieve Meta install referrer on first app open per Meta's documentation
  2. Report session via SESSION endpoint including meta_ref JSON parameter with required attributes

meta_ref Attributes:

Attribute Description
is_ct is_ct from Meta Install Referrer (0 or 1)
install_referrer install_referrer from Meta Install Referrer
actual_timestamp actual_timestamp from Meta Install Referrer (e.g., 1693978124)

Singular Links & Deep Linking

Implement deep linking and deferred deep linking support for Singular tracking links to enable seamless user experiences from campaigns to specific in-app content.

Deep links are clickable links leading users to specific content inside apps. When user clicks deep link on device with app installed, app opens and shows specific product or experience.

Resources: Deep Linking FAQ | Singular Links FAQ

Prerequisites

Platform Configuration

Client app must recognize Singular Links as iOS Universal Links or Android App Links.

Configuration guide: Singular Links Prerequisites


Deep Link Implementation

Capturing Deep Links

When app opens via deep link, capture and add openURL to SESSION request by appending URL value to openuri parameter. Required when using Singular Links.

Singular Link Parameters:

  • _ios_dl and _android_dl: Present when link generated with different deep link values per platform
  • _dl: Present when deep link values same for iOS and Android
  • _p: Present when passthrough parameter included

Deep Link Handler Code

App must have handler code parsing openURL and handling Singular Link parameters appropriately.

iOS - SwiftAndroid - Kotlin
class DeepLinkHandler {
    func handleURL(_ url: URL) {
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
            return
        }

        var params: [String: String] = [:]

        // Parse query parameters
        if let queryItems = components.queryItems {
            for item in queryItems {
                switch item.name {
                case "_dl":
                    params["deeplink"] = item.value
                case "_ios_dl":
                    params["ios_deeplink"] = item.value
                case "_p":
                    params["passthrough"] = item.value
                default:
                    break
                }
            }
        }

        // Handle the parsed parameters
        processDeepLinkParameters(params)
    }

    private func processDeepLinkParameters(_ params: [String: String]) {
        // Process the parameters as needed
        print("Processed parameters: \(params)")
    }
}

// In SceneDelegate or AppDelegate
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else { return }
    let handler = DeepLinkHandler()
    handler.handleURL(url)
}

Deferred Deep Linking

First-Install Deep Links

When app opens first time since install, enable deferred deep linking by adding parameters when reporting session to Singular.

Required Parameters:

  • install=true
  • ddl_enabled=true

Singular checks if app installed through tracking link with deferred deep link. If so, SESSION request returns:

  • deferred_deeplink: Deep link address—parse to show users correct product/experience
  • deferred_passthrough: Passthrough parameters added to deep link

Sample Response:

{
  "deferred_deeplink": "myapp://deferred-deeplink",
  "status": "ok",
  "deferred_passthrough": "passthroughvalue"
}

Dynamic Passthrough Parameters

Singular tracking links can include dynamic passthrough parameters for customized user experiences.

If organization configured dynamic passthrough for link, deep link URL includes _p parameter with URL-encoded JSON string value or unstructured string for content/experience routing.

More info: Dynamic Passthrough Parameters


Short Link Resolution

When app opens from shortened Singular Link, include parameter on SESSION request to resolve short link to long link.

Required Parameter: singular_link_resolve_required=true

Singular returns unshortened long link for parsing deep link and passthrough parameters in link handler.

Sample Response:

{
  "status": "ok",
  "resolved_singular_link": "https://myapp.sng.link/A59c0/nha7?_dl=myapp%3A%2F%2Fdeeplink&_ddl=myapp%3A%2F%2Fdeferred-deeplink&_p=passthroughvalue"
}

Additional Features

Implement cross-device tracking, revenue tracking, uninstall monitoring, and data privacy compliance for comprehensive analytics.

Cross-Device Tracking

Custom User ID Implementation

Leverage custom_user_id parameter to associate users with device-level sessions for cross-device reporting and user-level analytics.

Privacy Compliance: Adhere to data privacy policies by avoiding personally identifiable information (PII) in custom_user_id. Use hashed username, email, or randomly generated string as unique user identifier.

Enables comprehensive cross-device reporting, user-level data exports, and Internal BI postbacks while maintaining user privacy.

More info: Custom User ID Parameter


Revenue Tracking

In-App Purchase Reporting

Track revenue from in-app purchases for ROI analysis, campaign performance measurement, and export/postback enrichment.

Use EVENT endpoint with revenue parameters:

  • is_revenue_event: Marks event as revenue event (skip if event name is __iap__ or amount > 0)
  • purchase_receipt: Android/iOS In-App Purchase object—highly recommended for transaction details and report enrichment
  • receipt_signature (Android): Highly recommended for transaction validation and fraud prevention
  • amt: Revenue amount as Double (e.g., "amt=1.99")
  • cur: ISO 4217 currency code (e.g., "cur=USD")

Implementation guide: Subscription State Management


Uninstall Tracking

Silent Push Notification Setup

Track uninstalls using device silent push notifications by sending push token with every session notification.

Setup Requirements:

  1. Follow platform-specific uninstall tracking setup:
  2. Append platform-specific token to SESSION request:
    • iOS: apns_token (APNs device token)
    • Android: fcm (FCM device token)

iOS Install Receipt

Receipt Validation

Pass iOS install receipt in install_receipt parameter when reporting iOS session.

Swift
import Foundation
import StoreKit

class ReceiptManager {
    static func getInstallReceipt() - String? {
        if #available(iOS 18.0, *) {
            let semaphore = DispatchSemaphore(value: 0)
            var result: String?
            
            Task {
                do {
                    let transaction = try await AppTransaction.shared
                    result = transaction.jwsRepresentation
                    semaphore.signal()
                } catch {
                    debugPrint("Failed to get app transaction: \(error.localizedDescription)")
                    semaphore.signal()
                }
            }
            
            semaphore.wait()
            return result
            
        } else {
            guard let receiptURL = Bundle.main.appStoreReceiptURL else {
                debugPrint("Receipt URL not found")
                return nil
            }
            
            do {
                let receiptData = try Data(contentsOf: receiptURL, options: .uncached)
                return receiptData.base64EncodedString(options: [])
            } catch {
                debugPrint("Failed to read receipt: \(error.localizedDescription)")
                return nil
            }
        }
    }
}

Data Privacy Compliance

User Consent Handling

Notify Singular of end-user consent for data sharing to comply with GDPR, CCPA, and other privacy regulations.

Use data_sharing_options parameter to communicate user choice:

  • {"limit_data_sharing":false}: User consented (opted-in) to share information
  • {"limit_data_sharing":true}: User refused to share information

Singular uses limit_data_sharing in User Privacy Postbacks and passes information to partners requiring compliance.

Optional but Recommended: Parameter optional, but some attribution information only shared by partners when user explicitly opted-in.

More info: User Privacy and Limit Data Sharing