Enable page view signals in a native Android app

The page view signal captures when users open screens in your app. You can instrument all screens for full navigation coverage, or target specific screens — such as category pages or account screens — to enrich navigation context alongside higher-value signals. For screens with dedicated signal types, such as product detail or order confirmation, use the appropriate signal instead.

Reasons to enable:

  • Track navigation patterns across screens
  • Understand which screens receive most traffic
  • Identify drop-off points in user journeys
  • Segment users based on content consumption

Availability: Premium and Ultimate


Implementation considerations

When to fire the signal

Fire the page view signal after the screen is visible to the user.

// Fragment: fire in onViewCreated(), after UI setup is complete.
// Activity: fire in onResume() to capture both initial display and back-stack returns.
// Avoid onCreate() or onStart() — the view may not be fully rendered yet.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    Connect.logSignal(hashMapOf("signalType" to "pageView", "url" to "ProductScreen"))
}
// Use LaunchedEffect(Unit) inside the composable.
// This fires once when the composable enters the composition.

@Composable
fun ProductScreen() {
    LaunchedEffect(Unit) {
        Connect.logSignal(hashMapOf("signalType" to "pageView", "url" to "ProductScreen"))
    }
}

Screen naming

Use a consistent naming strategy across your app. Options:

  • Class name — use the Fragment or Activity class name (for example, "ProductDetailBottomSheet"). Simple and consistent.
  • Logical name — use a human-readable label (for example, "Product detail"). More meaningful in analytics but requires maintenance.

Whichever strategy you choose, apply it uniformly so navigation paths are comparable across sessions.

Contact mapping

Use the audience field to map the signal to a contact in Connect. Commonly used identifiers are email address, phone number, and customer ID.

Note: A customer ID mapped to the Contact key attribute in Connect is the most reliable identifier for known contacts. However, if no matching contact exists and the only attribute is a contact key, the signal is discarded — contact keys alone cannot create new contacts.

Sources of the identifier in an Android app:

  • In-memory session object (for example, UserSession.email)
  • SharedPreferences for persisted login state
  • Room database or other local store

The value must be a JSONObject where each key is a contact attribute name as it appears in Connect (including capitalization and spacing) and each value is the attribute value. For phone number attributes, use the E.164 format: +[country code][area code][phone number] — no spaces, dashes, or special characters. If the + symbol is omitted, Connect adds it automatically.

Note: We recommend attaching identifiers to as many signals as possible. If the user is not authenticated, omit audience — Connect will attempt to identify the visitor using other signals from the same session.


Configuration

Method

Connect.logSignal(data: HashMap<String?, Any?>?): Boolean

Sends the signal to the Acoustic Connect endpoint. The Connect SDK must be initialized via Connect.enable() before calling this method.

Pass all signal fields as a flat HashMap — the SDK handles the mapping to the backend signal structure automatically. The only exception is audience, which must be a JSONObject.

Signal fields

Required

FieldTypeDescription
signalTypeStringSignal type. Value: "pageView".
urlStringThe screen name or identifier for the screen the user has opened. Screen names are accepted as-is — there is no URL validation.

Optional

FieldTypeDescription
audienceJSONObjectKey-value pairs for contact mapping. Must be a flat JSONObject — not a HashMap. Keys must match contact attribute names exactly as they appear in Connect
categoryStringSignal category. Value: "Behavior"
descriptionStringA description of the signal
nameStringA label to differentiate this signal from others (for example, "pageView from Android app"). Max 256 characters
pageCategoryStringThe category the screen belongs to (for example, "clothing", "account")

Note: Pass audience as a JSONObject, not a HashMap. A HashMap value is silently dropped by the SDK serializer and the contact will not be mapped.

Required import

import org.json.JSONObject

Basic example

val data = hashMapOf<String?, Any?>(
    "signalType" to "pageView",
    "url" to "ProductDetailBottomSheet"
)
Connect.logSignal(data)

Complete example

This example fires a page view signal with optional contact mapping when a user is authenticated.

import org.json.JSONObject
import com.acoustic.connect.android.connectmod.Connect

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // Set up UI ...

    val data = hashMapOf<String?, Any?>(
        "signalType" to "pageView",
        "url" to "ProductDetailBottomSheet",
        "pageCategory" to "home goods"
    )

    // audience must be JSONObject — HashMap values are silently dropped
    UserSession.email?.let { email ->
        data["audience"] = JSONObject().put("Email Address", email)
    }

    Connect.logSignal(data)
}
import org.json.JSONObject
import androidx.compose.runtime.LaunchedEffect
import com.acoustic.connect.android.connectmod.Connect

@Composable
fun ProductDetailScreen(userEmail: String?) {

    LaunchedEffect(Unit) {
        val data = hashMapOf<String?, Any?>(
            "signalType" to "pageView",
            "url" to "ProductDetailScreen",
            "pageCategory" to "home goods"
        )

        // audience must be JSONObject — HashMap values are silently dropped
        userEmail?.let { email ->
            data["audience"] = JSONObject().put("Email Address", email)
        }

        Connect.logSignal(data)
    }
}

Best practices

  1. Fire the signal consistently on every screen in your app.
  2. Use a single naming convention for url across the team.
  3. Attach an audience identifier whenever the user is authenticated.
  4. Avoid firing duplicate signals — check that the signal fires once per screen display, not on every layout pass or configuration change.

Troubleshooting

Signal not appearing in Connect?

  • Confirm Connect.enable() is called before logSignal.
  • Check that logSignal returns true. A false return indicates the SDK rejected the call (SDK not initialized or capture disabled).
  • Verify the appKey and postMessageUrl match the Connect org you're checking.

Contact not created or updated?

  • Confirm audience is a JSONObject, not a HashMap.
  • Verify attribute key names match exactly how they appear in Connect — including capitalization and spacing.

Duplicate signals on the same screen?

  • Check that the signal call is not inside a method that runs on configuration changes (for example, screen rotation). Prefer onViewCreated over onResume for Fragments if back-stack returns should not re-fire.

Related pages