mcpField
C
contentsquare-ios-sdk

contentsquare-ios-sdk

github.com/contentsquareDevelopment238 installsUpdated 6d ago
Repository

About contentsquare-ios-sdk

A skill that helps AI agents integrate or upgrade the Contentsquare SDK in iOS apps. It covers project health checks, SDK startup, consent, screen and transaction tracking, Session Replay masking, and WebView registration.

Key features

  1. 01Check project config by data source or bundle ID
  2. 02Guide SPM and CocoaPods installation
  3. 03Configure SDK startup and user consent
  4. 04Track screens, transactions, events, and identity
  5. 05Set Session Replay privacy masking
  6. 06Register WebViews and configure in-app features

Use cases

  1. 01Integrate Contentsquare SDK into an iOS app
  2. 02Upgrade or troubleshoot SDK configuration
  3. 03Implement screen and purchase tracking
  4. 04Mask sensitive content in Session Replay

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/contentsquare/agents --skill contentsquare-ios-sdk

After installing, type/contentsquare-ios-sdkin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
api-reference.md
ios-in-app-features.md
session-replay.md
xcode-project-setup.md
scripts/xcode_spm_setup/
.gitignore
Package.swift
scripts/xcode_spm_setup/Sources/
main.swift

Details

From the project README

Contentsquare iOS SDK Integration

This skill helps AI agents integrate or upgrade the Contentsquare iOS SDK in client applications.

MANDATORY FIRST STEP -- Contentsquare project healthcheck

Before ANY Contentsquare work in a conversation -- integration, debugging, configuration questions, code changes -- run this healthcheck exactly once per conversation. Do not skip it. Do not defer it to later in the task.

  1. Announce it first. Tell the user what you are about to do, for example:

    "Before we start, I'll run a quick healthcheck of your Contentsquare project: I'll ask for your data source ID (or read your app's bundle id if you don't have one), call the Contentsquare healthcheck endpoint, and show you the current project configuration. Then we'll continue."

  2. Ask the user for their Contentsquare data source ID(s) first. For example: "Do you have a Contentsquare data source ID? There can be one or several." Use only the IDs the user gives -- never invent one.

    • The user gives one or more data source IDs → check by data source ID only (v3). Skip step 3.
    • The user only has an environment ID → check by bundle id only (v2): an environment ID is not a data source ID and never works in the v3 path.
    • The user has none, does not know, or skips the question → check by bundle id only (v2).
  3. Resolve the bundle id (only without a data source ID). Read PRODUCT_BUNDLE_IDENTIFIER from the Xcode project (*.xcodeproj/project.pbxproj), or CFBundleIdentifier from Info.plist. Resolve any $(...) build-setting variables to their literal value before using it.

  4. Call the endpoint -- one version only, never both. The platform segment is literally ios -- no other value is accepted.

    With data source IDs (v3), once per ID:

    curl -s "https://mobile-production.content-square.net/healthcheck/ios/config/v3/<dataSourceId>.json"
    

    If an ID does not return 200, tell the user -- it may be an environment ID or a typo -- and ask whether you may look for the data source ID in the code yourself: it is the ID passed to CSQ.start(dataSourceID:) (follow it to its literal value if it comes from a constant or a config file). If they agree and you find a different ID, run the v3 check once with it. If they decline or there is none in the code, continue without it.

    Without a data source ID (v2):

    curl -s "https://mobile-production.content-square.net/healthcheck/ios/config/v2/<bundleId>.json"
    
  5. Report a short summary of these values, for each call that returned 200:

    ReportJSON path
    Project IDcs_project_id
    Tracking enabledproject_configurations.project_config.enabled
    Session Replayproject_configurations.project_config.session_replay -- recording_rate, record_via_cellular_network, recording_quality_wifi, srm_enabled, user_identifier
    Enabled feature flagsproject_configurations.project_config.feature_flags -- only entries where enabled == true, with name and min_version

    For v3 calls, also report the Environment ID (environment_id). If the responses differ, call that out explicitly.

  6. Then continue with the user's actual request.

Failure handling. 403 Invalid health-check path means the URL shape is wrong -- re-check the ios segment, the v2/v3 segment and the id, and do not alter the path structure. A non-200 proxied from upstream means that data source ID or bundle id has no Contentsquare configuration: say so, then continue anyway -- do not retry with the other version (the only retry is the code lookup in step 4). This healthcheck is informational only and must never block the user's task.

Install

Swift Package Manager (recommended)

See xcode-project-setup to add https://github.com/ContentSquare/apple-sdk

CocoaPods
pod 'ContentsquareSDK'

Then pod install.

Quick Start

import ContentsquareSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        CSQ.start(dataSourceID: "your-data-source-id") // or start(environmentID:) if no data source ID
        CSQ.optIn() // TODO: Only call after user consent. The SDK stays inactive until optIn() is called. Implement a consent prompt and call optIn()/optOut() based on user choice.
        return true
    }
}

SwiftUI:

import ContentsquareSDK

@main
struct MyApp: App {
    init() {
        CSQ.start(dataSourceID: "your-data-source-id") // or start(environmentID:) if no data source ID
        CSQ.optIn() // TODO: Only call after user consent. The SDK stays inactive until optIn() is called. Implement a consent prompt and call optIn()/optOut() based on user choice.
    }

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

For DXA-only (no Product Analytics), use CSQ.start() without parameters.

It is very important that screens should be tracked, otherwise Session Replay will not work. You can track screens manually with trackScreenview() in viewWillAppear(_:) (UIKit) or .onAppear (SwiftUI):

CSQ.trackScreenview("HomeScreen")

Before wrapping up the integration, make sure you are handling WebViews if they are present in the app. WebViews are not automatically tracked, and every WebView must be registered. Check the WebView Tracking section below for details.

Integration Workflow

When integrating Contentsquare into an iOS app, follow this order:

  1. Add dependency -- SPM: https://github.com/ContentSquare/apple-sdk.git, or CocoaPods: pod 'ContentsquareSDK'.
  2. Start the SDK -- Call CSQ.start(dataSourceID:) (preferred) or CSQ.start(environmentID:) in application(_:didFinishLaunchingWithOptions:) or App.init(). For DXA-only, use CSQ.start().
  3. Implement consent -- Add CSQ.optIn() with a TODO comment for the customer to manage their own consent flow. The SDK stays inactive until optIn() is called.
  4. Set up screen tracking -- Call CSQ.trackScreenview(_:) on each screen appearance (e.g., viewWillAppear, .onAppear).
  5. Track transactions -- Use CSQ.trackTransaction(Transaction(id:, value:, currency:)) for purchases.
  6. Configure Session Replay masking -- Use CSQ.setDefaultMasking(true) globally, then CSQ.unmask(view) / CSQ.mask(view) or SwiftUI .csqMaskContents(true) for sensitive content.
  7. Set up error tracking -- Use CSQ.onCrashReporterStart { } to coordinate with third-party crash reporters.
  8. Register WebViews -- Call CSQ.registerWebView(webView) for every WKWebView instance.
  9. Add identity -- Use identify() for Product Analytics or sendUserIdentifier() for Experience Analytics.
  10. Configure in-app features -- Add the custom URL scheme and handle the deeplink. This step is mandatory to access screenshot capture, SDK logs, Log Visualizer, and Zoning Analysis. See references/ios-in-app-features.md.

API Surface

Always use CSQ from import ContentsquareSDK. The Contentsquare class is the legacy SDK and should not be used.

Lifecycle
MethodPurpose
start()Start the SDK. Must be called before any other API.
stop()Shut down the SDK completely.
pauseTracking()Pause data collection (for sensitive screens).
resumeTracking()Resume after pauseTracking().

Avoid using pauseTracking and resumeTracking unless you are specifically asked for it.

Start Configuration
MethodUse CaseOnboarding priority
start(dataSourceID:, options:)Both DXA and Product Analytics with data source ID1st choice for new clients -- ask for this first
start(environmentID:, options:)Product Analytics with environment ID2nd choice if no data source ID is available
start(options:)Digital Experience Analytics onlyFallback only -- when neither ID is available or DXA-only is explicitly requested

Recommended onboarding flow:

  1. Ask the user: "Do you have a Contentsquare data source ID?" (skip the question if they already answered it during the healthcheck). If yes, use CSQ.start(dataSourceID: "your-data-source-id").
  2. If not, ask: "Do you have an environment ID?" If yes, use CSQ.start(environmentID: "your-env-id").
  3. Only if neither is available (or the user explicitly wants DXA-only), fall back to CSQ.start().

Do not invent an ID. Do not silently default to DXA without asking.

Options include: .uploadInterval, .baseURL, .disablePageviewAutocapture, .enableNativeAutocapture, .enablePushNotificationAutocapture, .sessionReplayAutoStart.

Privacy
MethodPurpose
optIn()Opt the device into tracking. Generates user ID, starts immediately.
optOut()Opt out permanently. Stops until optIn() or app reinstall.
Identity
MethodContextPurpose
identify("userId")Product AnalyticsSet user identity. Different ID triggers new session. Max 255 chars.
resetIdentity()Product AnalyticsClear identity.
sendUserIdentifier("userId")Digital Experience AnalyticsSend hashed user ID. Max 100 chars.
Screen Tracking
MethodPurpose
trackScreenview(_:, cvars:)Track a screen view with optional custom variables.

CustomVar(index:, name:, value:) -- index (UInt32), name (String, max 512 chars), value (String, max 255 chars).

Transactions
let transaction = Transaction(id: "order_123", value: 29.99, currency: .usd)
CSQ.trackTransaction(transaction)

Currency is an ISO 4217 enum (e.g., .usd, .eur, .gbp).

Custom Events and Properties
MethodPurpose
trackEvent(_:, properties:)Track a named event with optional properties.
addDynamicVar(DynamicVar)Add session-level dynamic variable (EA).
addUserProperties([String: PropertyValue])Set user-level properties (PA).
addEventProperties([String: PropertyValue])Set properties on all future events (PA).
removeEventProperty("key")Remove one event property.
clearEventProperties()Remove all event properties.

PropertyValue in Swift: String, Substring, Bool, Double, Float, Int, Int64, Int32, Int16, Int8.

DynamicVar(key:, value:) -- value is String (key max 512 chars, value max 255 chars) or UInt32 (key max 50 chars).

Session Replay Masking
MethodPurpose
setDefaultMasking(Bool)Set global masking state. Note: text inputs stay masked even when set to false.
mask(UIView)Mask a specific view and its subviews.
unmask(UIView)Unmask a specific view.
mask(viewsOfType: UIView.Type)Mask all views of a type (DXA).
unmask(viewsOfType: UIView.Type)Unmask all views of a type (DXA).
ignoreInteractions(UIView)Ignore interactions on a specific view (PA).
maskTexts(Bool)Mask all text content (UILabel, SwiftUI Text).
maskImages(Bool)Mask all image components (UIImageView, SwiftUI Image).
maskTextInputs(Bool)Mask all text input fields (UITextField, UITextView, SwiftUI TextField, SecureField, TextEditor).

UIKit IBInspectable properties: view.csqMaskContents = true, view.csqIgnoreInteractions = true, view.csqIgnoreInnerHierarchy = true.

SwiftUI modifiers: .csqMaskContents(true), .csqIgnoreInteractions(true).

WebView Tracking
MethodPurpose
registerWebView(WKWebView)Register a WKWebView for tracking.
unregisterWebView(WKWebView)Unregister a WKWebView.

WebViews are not automatically tracked. Every WKWebView instance must be registered.

Surveys
MethodPurpose
triggerSurvey("triggerName")Trigger a survey by predefined trigger name (DXA VoC).
Error Tracking
MethodPurpose
onCrashReporterStart { enabled in }Callback when crash reporter initializes (DXA).
setURLMaskingPatterns(["pattern"])Mask sensitive URL paths (DXA).
trackNetworkMetric(NetworkMetric)Track HTTP network errors (DXA).
CSInApp

In-app features must be configured in the app for any of these APIs to work. Without the URL scheme and deeplink handler in place, handle(url:) will never be triggered and in-app features (Screenshot Capture, SDK Logs, Log Visualizer) will not be accessible. See references/ios-in-app-features.md for the full setup.

MethodPurpose
handle(url:)Handle CSInApp URL scheme activation (DXA). Call in application(_:open:options:).
csInAppRead/write property to manually activate or deactivate in-app debug features (DXA).
Debug and Metadata
APIPurpose
logLevel = .debugSet log level (.none, .error, .warn, .info, .debug, .trace)
logChannel = customChannelRoute logs to custom logger, replacing the default console output.
addLogChannel(_:) / removeLogChannel(_:)Add or remove a log channel alongside the existing ones.
metadataAccess session metadata.
metadata.onChange { metadata in }Listen for metadata changes.

Metadata properties: userID, sessionID, projectID, environmentID, sessionReplayURL, identity.

Common Patterns

1. Full initialization with Product Analytics
import ContentsquareSDK

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    CSQ.start(dataSourceID: "your-data-source-id", options: [.enableNativeAutocapture: true]) // or start(environmentID:) if no data source ID
    CSQ.optIn() // TODO: Only call after user consent
    return true
}
2. Track a purchase
let transaction = Transaction(id: "txn_abc", value: 49.99, currency: .eur)
CSQ.trackTransaction(transaction)
3. Custom event with properties
CSQ.trackEvent(
    "add_to_cart",
    properties: ["product_id": "sku_123", "quantity": 2, "is_promo": true]
)
4. Crash reporter coordination
CSQ.onCrashReporterStart { enabled in
    if enabled {
        // Start Firebase Crashlytics or other crash reporter here
    }
}
5. SwiftUI screen tracking
struct ProductDetailView: View {
    var body: some View {
        VStack { /* content */ }
            .onAppear {
                CSQ.trackScreenview("ProductDetail")
            }
    }
}
6. WebView registration
let webView = WKWebView()
CSQ.registerWebView(webView)
// When done or on deinit:
CSQ.unregisterWebView(webView)

Platform Guidance

UIKit
  • Call CSQ.start() in application(_:didFinishLaunchingWithOptions:).
  • Track screens in viewWillAppear(_:) with CSQ.trackScreenview(_:).
  • Mask views with CSQ.mask(view) / view.csqMaskContents = true.
SwiftUI
  • Call CSQ.start() in App.init().
  • Track screens with .onAppear { CSQ.trackScreenview("ScreenName") }.
  • Mask views with .csqMaskContents(true) modifier.
  • Ignore interactions with .csqIgnoreInteractions(true).

Migration from older SDK versions

Current SDK version: 1.11.x

This section covers migration from SDK versions 1.0–1.6 to 1.11.x. If you are migrating from an older version, apply all changes below. They are cumulative — a project on 1.0 must apply every step.

Step 1 — Upgrade SDK version to 1.11.x

Check whether the SDK is up to date. If not, upgrade the Contentsquare SPM package to 1.11.x. See xcode-project-setup for upgrading the Swift Package.

Step 2 — Replace the deprecated initialization pattern

The two-step CSQ.configureProductAnalytics(environmentID:, additionalOptions:) + CSQ.start() pattern was removed. Replace it with the unified CSQ.start(environmentID:, options:) or CSQ.start(dataSourceID:, options:).

// Old (removed — will not compile in 1.11.x)
CSQ.configureProductAnalytics(environmentID: "your-env-id", additionalOptions: [.enableUIKitAutocapture: true])

// New
CSQ.start(environmentID: "your-env-id", options: [.enableNativeAutocapture: true])

If the project has a data source ID (preferred for new clients), use start(dataSourceID:) instead.

Step 3 — Rename options
Old nameNew name
.enableUIKitAutocapture.enableNativeAutocapture
ProductAnalyticsOption (type)AnalyticsOption (ProductAnalyticsOption is a deprecated typealias — prefer AnalyticsOption in new code)
Step 4 — Delete removed options

The following options were removed entirely from AnalyticsOption. Delete every occurrence from all start(...) or configureProductAnalytics(...) call sites — the project will not compile if any remain:

  • .captureVendorID
  • .captureAdvertiserID
  • .clearEventPropertiesOnNewUser
  • .messageBatchByteLimit
  • .messageBatchMessageLimit
  • .resumePreviousSession
  • .pruningLookBackWindow
  • .disableScreenviewForwardToDXA
  • .disableScreenviewForwardToPA
  • .interactionHierarchyCaptureLimit
  • .disableInteractionTextCapture
  • .disableInteractionAccessibilityLabelCapture
Step 5 — Review Session Replay auto-start behavior

A new option .sessionReplayAutoStart (defaults to true) was added. No action required if you want the default behavior. Set it to false only if you need to control Session Replay manually:

CSQ.start(environmentID: "your-env-id", options: [.sessionReplayAutoStart: false])
// Then start/stop manually:
CSQ.startSessionReplay()
CSQ.stopSessionReplay() // terminal — cannot be restarted in the same SDK lifetime
Migration checklist (1.0–1.6 → 1.11.x)
  • SPM package is updated to 1.11.x
  • Replaced configureProductAnalytics + start() with unified CSQ.start(environmentID:options:) or CSQ.start(dataSourceID:options:)
  • Renamed .enableUIKitAutocapture → .enableNativeAutocapture
  • Renamed ProductAnalyticsOption type references → AnalyticsOption
  • Deleted all removed options from every call site
  • Build succeeds with no deprecated-API warnings related to the above

In-App Features (Mandatory Setup)

In-app features (Screenshot Capture, SDK Logs, Log Visualizer, Zoning Analysis) are essential for Contentsquare users to validate and debug the integration. They are not optional — without this setup, Contentsquare users cannot access any of these tools.

Two steps are required:

  1. Add the cs-$(PRODUCT_BUNDLE_IDENTIFIER) URL scheme to Info.plist.
  2. Call CSQ.handle(url: url) in the appropriate deeplink handler (AppDelegate, SceneDelegate, or .onOpenURL in SwiftUI).

Always include this setup when integrating the SDK. Refer to references/ios-in-app-features.md for the complete implementation guide.

Important Constraints

  • Ask for IDs in this order: Before integrating, ask the user (1) for a Contentsquare data source ID (reuse the healthcheck answer) -- preferred for new clients. (2) If they don't have one, ask for an environment ID. (3) Only if they have neither (or explicitly want DXA-only), fall back to CSQ.start(). Do not invent an ID and do not silently default to DXA without asking.
  • Scan for WebViews: During integration, search the codebase for any existing WKWebView usage. WebViews are not automatically tracked -- every instance must be registered with CSQ.registerWebView(_:). Do not skip this step.
  • In-app features are mandatory: Always configure the URL scheme (cs-$(PRODUCT_BUNDLE_IDENTIFIER)) and CSQ.handle(url:) deeplink handler. Without this, Contentsquare users cannot use Screenshot Capture, SDK Logs, Log Visualizer, or Zoning Analysis. See references/ios-in-app-features.md.
  • Platform support: iOS only. Check compatibility docs.
  • Property types: Only String, Bool, and numeric types are accepted as PropertyValue.
  • DynamicVar limits: String variant: key max 512 chars, value max 255 chars. Int variant: key max 50 chars, value is UInt32.
  • userIdentifier: Max 255 characters for identify(), max 100 characters for sendUserIdentifier().
  • Privacy: Never auto-opt-in. Always implement a consent flow.
  • PII: Never pass emails, passwords, or real names in screen names, event names, or properties.
  • Environment IDs: Never hardcode -- use configuration or environment variables.

Integration Checklist

Before considering an integration complete, verify:

  • Dependency added (SPM or CocoaPods)
  • CSQ.start(dataSourceID:), CSQ.start(environmentID:), or CSQ.start() called as the first SDK call in AppDelegate or App.init
  • CSQ.optIn() added with TODO comment for customer consent flow
  • Screen tracking is set up for all main screens
  • Session Replay masking configured for sensitive content
  • All WKWebView instances registered with CSQ.registerWebView(_:)
  • Crash reporter coordination via CSQ.onCrashReporterStart { }
  • No PII in screen names, event names, or properties
  • Transaction tracking uses the Currency enum
  • IDs (dataSourceID, environmentID) are not hardcoded
  • In-app features configured: cs-$(PRODUCT_BUNDLE_IDENTIFIER) URL scheme added to Info.plist and CSQ.handle(url:) called in the deeplink handler

References

Comments

Markdown supported