Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,50 @@
---
name: contentsquare-flutter-sdk
description: Integrate or upgrade the Contentsquare Flutter SDK -- Session Replay, screen tracking, transactions, analytics, masking, privacy opt-in/out. Use when working with Contentsquare, CSQ, CSQ.start, StartConfig, AnalyticsOptions, ProductAnalyticsOptions, CSQNavigatorObserver, CSQNavigatorAutoRouteObserver, auto_route, AutoRoute, GoRouter, go_router, CSQWebViewWrapper, configureProductAnalytics, or migrating from the legacy `Contentsquare()` API to `CSQ()` (v3.x to v4.x) or from 4.1.x to 4.4.x.
description: Integrate or upgrade the Contentsquare Flutter SDK -- Session Replay, screen tracking, transactions, analytics, masking, privacy opt-in/out. Always starts with a mandatory Contentsquare project healthcheck (resolve the Android and iOS bundle ids, call the healthcheck endpoint, report project health) before any other work. Use when working with Contentsquare, CSQ, CSQ.start, StartConfig, AnalyticsOptions, ProductAnalyticsOptions, CSQNavigatorObserver, CSQNavigatorAutoRouteObserver, auto_route, AutoRoute, GoRouter, go_router, CSQWebViewWrapper, configureProductAnalytics, or migrating from the legacy `Contentsquare()` API to `CSQ()` (v3.x to v4.x) or from 4.1.x to 4.4.x.
---

# Contentsquare Flutter SDK Integration

> This skill helps AI agents integrate or upgrade the Contentsquare Flutter 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 read your app's bundle ids, call the Contentsquare healthcheck endpoint, and show you the current project configuration. Then we'll continue."

2. **Resolve the bundle ids -- a Flutter app has TWO, and they are frequently different strings.** Resolve each one separately; never assume they match.

| Platform | Where to read it |
|---|---|
| Android | `applicationId` in `android/app/build.gradle(.kts)` (fall back to `namespace`, or `package` in `AndroidManifest.xml`) |
| iOS | `PRODUCT_BUNDLE_IDENTIFIER` in `ios/Runner.xcodeproj/project.pbxproj` (or `CFBundleIdentifier` in `ios/Runner/Info.plist`), resolving any `$(...)` variables |

3. **Call the endpoint once per platform that exists.** The platform segment must be literally `ios` or `android`. There is no Flutter platform value -- never send one.

```bash
curl -s "https://mobile-production.content-square.net/healthcheck/android/config/v2/<androidApplicationId>.json"
curl -s "https://mobile-production.content-square.net/healthcheck/ios/config/v2/<iosBundleId>.json"
```

If only one platform is present in the project, query only that one. If you cannot resolve one of the ids, ask the user which platform to check rather than guessing.

4. **Report a short summary** of these values, per platform queried:

| Report | JSON path |
|---|---|
| Project ID | `cs_project_id` |
| Tracking enabled | `project_configurations.project_config.enabled` |
| Session Replay | `project_configurations.project_config.session_replay` -- `recording_rate`, `record_via_cellular_network`, `recording_quality_wifi`, `srm_enabled`, `user_identifier` |
| Enabled feature flags | `project_configurations.project_config.feature_flags` -- only entries where `enabled == true`, with `name` and `min_version` |

Android and iOS may map to different Contentsquare projects. If the two responses differ, call that out explicitly.

5. **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`/`android` segment and the bundle id, and do not alter the path structure. A non-200 proxied from upstream means that bundle id has no Contentsquare project configured: say so, then continue anyway. This healthcheck is **informational only and must never block the user's task**.

## Install

```yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ To use Contentsquare in-app features on iOS (screenshot capture, SDK logs, Log V
The app must be opened via a custom URL scheme.

**Using Xcode:**

1. Open the project settings
2. Select the app target
3. Select the `Info` settings
Expand Down Expand Up @@ -119,33 +118,27 @@ struct MyApp: App {
Once configured, in-app features can be enabled by:

### 1. Scanning QR code (physical device)

From the Contentsquare platform menu, scan the displayed QR code with the device.

### 2. Custom link (simulator)

Copy the deeplink from the Contentsquare platform and paste it in Safari on the Simulator.

### 3. Terminal command (simulator)

```bash
xcrun simctl openurl booted "CUSTOM_LINK"
```

Replace `CUSTOM_LINK` with the actual deeplink from the Contentsquare platform.

## Debugging with logs

By default, only one startup log is visible:

```
CSLIB ℹ️ Info: Contentsquare SDK vX.X.X starting in app: {{bundleID}}
```

To enable all logs, activate in-app features. Logs appear when in-app features are enabled and stop when disabled.

**To view logs:**

1. Connect the device to Mac (or use same Wi-Fi for wireless debugging)
2. Open macOS Console app (enable Info messages via Action > Include Info Messages) or Xcode
3. Filter logs on `CSLIB`
Expand All @@ -161,9 +154,9 @@ After completing the setup:

## Troubleshooting

| Issue | Solution |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Deeplink doesn't open the app | Verify the URL scheme in `Info.plist` matches `cs-$(PRODUCT_BUNDLE_IDENTIFIER)`. Check bundle identifier in Xcode. |
| No overlay appears | Ensure `CSQ.handle(url:)` is called in the correct lifecycle method. Check console for errors. |
| `ContentsquareModule` not found | Run `pod install` in the `ios/` directory. Ensure the Contentsquare Flutter plugin is properly installed. |
| Logs not appearing | Ensure in-app features are enabled. Check Console app filter settings (include Info messages). |
| Issue | Solution |
|-------|----------|
| Deeplink doesn't open the app | Verify the URL scheme in `Info.plist` matches `cs-$(PRODUCT_BUNDLE_IDENTIFIER)`. Check bundle identifier in Xcode. |
| No overlay appears | Ensure `CSQ.handle(url:)` is called in the correct lifecycle method. Check console for errors. |
| `ContentsquareModule` not found | Run `pod install` in the `ios/` directory. Ensure the Contentsquare Flutter plugin is properly installed. |
| Logs not appearing | Ensure in-app features are enabled. Check Console app filter settings (include Info messages). |
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ When no `maskingConfig` is provided, the SDK applies sensible defaults. See [def

### What each field masks

| Field | What gets masked | Example widgets |
| ------------------ | -------------------- | ----------------------------------------------- |
| `maskTexts` | All text content | `Text`, `RichText` |
| `maskTextFields` | Input field content | `TextField`, `TextFormField` |
| `maskImages` | Image content | `Image`, `Image.network`, `Image.asset` |
| `maskSvgImages` | SVG pictures | `flutter_svg` widgets |
| `maskCharts` | Chart content | `fl_chart` widgets |
| Field | What gets masked | Example widgets |
|-------|-----------------|-----------------|
| `maskTexts` | All text content | `Text`, `RichText` |
| `maskTextFields` | Input field content | `TextField`, `TextFormField` |
| `maskImages` | Image content | `Image`, `Image.network`, `Image.asset` |
| `maskSvgImages` | SVG pictures | `flutter_svg` widgets |
| `maskCharts` | Chart content | `fl_chart` widgets |
| `maskCustomPaints` | Custom-drawn content | Your `CustomPaint` widgets (not framework ones) |
| `maskInteractions` | User interactions | Taps, swipes (Product Analytics only) |
| `maskInteractions` | User interactions | Taps, swipes (Product Analytics only) |

### Masking precedence

Expand Down Expand Up @@ -101,10 +101,10 @@ await CSQ().startSessionReplay();
await CSQ().stopSessionReplay();
```

| Method | Effect |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `startSessionReplay()` | Starts SR. Behaves like the automatic start once invoked. **One-shot:** intended to be called at most once when `sessionReplayAutoStart: false`. |
| `stopSessionReplay()` | Stops SR only. Other tracking (events, pageviews, identify, etc.) keeps running. **Terminal:** once called, SR cannot be re-started -- subsequent `startSessionReplay()` calls have no effect. Use `CSQ().stop()` to stop everything. |
| Method | Effect |
|--------|--------|
| `startSessionReplay()` | Starts SR. Behaves like the automatic start once invoked. **One-shot:** intended to be called at most once when `sessionReplayAutoStart: false`. |
| `stopSessionReplay()` | Stops SR only. Other tracking (events, pageviews, identify, etc.) keeps running. **Terminal:** once called, SR cannot be re-started -- subsequent `startSessionReplay()` calls have no effect. Use `CSQ().stop()` to stop everything. |

> **No restart support.** This API only handles **starting** and **stopping** SR -- it is not a pause/resume mechanism. Plan the customer's flow accordingly: start SR at the beginning of the journey you want to record, and only call `stopSessionReplay()` when you are sure the recording is complete for the rest of the session.

Expand Down
40 changes: 39 additions & 1 deletion skills/contentsquare-flutter-sdk/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,50 @@
---
name: contentsquare-flutter-sdk
description: Integrate or upgrade the Contentsquare Flutter SDK -- Session Replay, screen tracking, transactions, analytics, masking, privacy opt-in/out. Use when working with Contentsquare, CSQ, CSQ.start, StartConfig, AnalyticsOptions, ProductAnalyticsOptions, CSQNavigatorObserver, CSQNavigatorAutoRouteObserver, auto_route, AutoRoute, GoRouter, go_router, CSQWebViewWrapper, configureProductAnalytics, or migrating from the legacy `Contentsquare()` API to `CSQ()` (v3.x to v4.x) or from 4.1.x to 4.4.x.
description: Integrate or upgrade the Contentsquare Flutter SDK -- Session Replay, screen tracking, transactions, analytics, masking, privacy opt-in/out. Always starts with a mandatory Contentsquare project healthcheck (resolve the Android and iOS bundle ids, call the healthcheck endpoint, report project health) before any other work. Use when working with Contentsquare, CSQ, CSQ.start, StartConfig, AnalyticsOptions, ProductAnalyticsOptions, CSQNavigatorObserver, CSQNavigatorAutoRouteObserver, auto_route, AutoRoute, GoRouter, go_router, CSQWebViewWrapper, configureProductAnalytics, or migrating from the legacy `Contentsquare()` API to `CSQ()` (v3.x to v4.x) or from 4.1.x to 4.4.x.
---

# Contentsquare Flutter SDK Integration

> This skill helps AI agents integrate or upgrade the Contentsquare Flutter 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 read your app's bundle ids, call the Contentsquare healthcheck endpoint, and show you the current project configuration. Then we'll continue."

2. **Resolve the bundle ids -- a Flutter app has TWO, and they are frequently different strings.** Resolve each one separately; never assume they match.

| Platform | Where to read it |
|---|---|
| Android | `applicationId` in `android/app/build.gradle(.kts)` (fall back to `namespace`, or `package` in `AndroidManifest.xml`) |
| iOS | `PRODUCT_BUNDLE_IDENTIFIER` in `ios/Runner.xcodeproj/project.pbxproj` (or `CFBundleIdentifier` in `ios/Runner/Info.plist`), resolving any `$(...)` variables |

3. **Call the endpoint once per platform that exists.** The platform segment must be literally `ios` or `android`. There is no Flutter platform value -- never send one.

```bash
curl -s "https://mobile-production.content-square.net/healthcheck/android/config/v2/<androidApplicationId>.json"
curl -s "https://mobile-production.content-square.net/healthcheck/ios/config/v2/<iosBundleId>.json"
```

If only one platform is present in the project, query only that one. If you cannot resolve one of the ids, ask the user which platform to check rather than guessing.

4. **Report a short summary** of these values, per platform queried:

| Report | JSON path |
|---|---|
| Project ID | `cs_project_id` |
| Tracking enabled | `project_configurations.project_config.enabled` |
| Session Replay | `project_configurations.project_config.session_replay` -- `recording_rate`, `record_via_cellular_network`, `recording_quality_wifi`, `srm_enabled`, `user_identifier` |
| Enabled feature flags | `project_configurations.project_config.feature_flags` -- only entries where `enabled == true`, with `name` and `min_version` |

Android and iOS may map to different Contentsquare projects. If the two responses differ, call that out explicitly.

5. **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`/`android` segment and the bundle id, and do not alter the path structure. A non-200 proxied from upstream means that bundle id has no Contentsquare project configured: say so, then continue anyway. This healthcheck is **informational only and must never block the user's task**.

## Install

```yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ To use Contentsquare in-app features on iOS (screenshot capture, SDK logs, Log V
The app must be opened via a custom URL scheme.

**Using Xcode:**

1. Open the project settings
2. Select the app target
3. Select the `Info` settings
Expand Down Expand Up @@ -119,33 +118,27 @@ struct MyApp: App {
Once configured, in-app features can be enabled by:

### 1. Scanning QR code (physical device)

From the Contentsquare platform menu, scan the displayed QR code with the device.

### 2. Custom link (simulator)

Copy the deeplink from the Contentsquare platform and paste it in Safari on the Simulator.

### 3. Terminal command (simulator)

```bash
xcrun simctl openurl booted "CUSTOM_LINK"
```

Replace `CUSTOM_LINK` with the actual deeplink from the Contentsquare platform.

## Debugging with logs

By default, only one startup log is visible:

```
CSLIB ℹ️ Info: Contentsquare SDK vX.X.X starting in app: {{bundleID}}
```

To enable all logs, activate in-app features. Logs appear when in-app features are enabled and stop when disabled.

**To view logs:**

1. Connect the device to Mac (or use same Wi-Fi for wireless debugging)
2. Open macOS Console app (enable Info messages via Action > Include Info Messages) or Xcode
3. Filter logs on `CSLIB`
Expand All @@ -161,9 +154,9 @@ After completing the setup:

## Troubleshooting

| Issue | Solution |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Deeplink doesn't open the app | Verify the URL scheme in `Info.plist` matches `cs-$(PRODUCT_BUNDLE_IDENTIFIER)`. Check bundle identifier in Xcode. |
| No overlay appears | Ensure `CSQ.handle(url:)` is called in the correct lifecycle method. Check console for errors. |
| `ContentsquareModule` not found | Run `pod install` in the `ios/` directory. Ensure the Contentsquare Flutter plugin is properly installed. |
| Logs not appearing | Ensure in-app features are enabled. Check Console app filter settings (include Info messages). |
| Issue | Solution |
|-------|----------|
| Deeplink doesn't open the app | Verify the URL scheme in `Info.plist` matches `cs-$(PRODUCT_BUNDLE_IDENTIFIER)`. Check bundle identifier in Xcode. |
| No overlay appears | Ensure `CSQ.handle(url:)` is called in the correct lifecycle method. Check console for errors. |
| `ContentsquareModule` not found | Run `pod install` in the `ios/` directory. Ensure the Contentsquare Flutter plugin is properly installed. |
| Logs not appearing | Ensure in-app features are enabled. Check Console app filter settings (include Info messages). |
Loading
Loading