Connect your stack

Optiview works with tools your team already uses

Optiview understands visitor behavior. Your GTM, Adobe, CMS, or app decides what visitors see — calmer modules, fewer interruptions, better continuity.

What teams do with Optiview

ToolTypical experience change
GTMSuppress interruptions when visitors are uncertain
Adobe TargetShow calmer experiences when friction increases
ReactAdapt modules before login
SegmentPass anonymous context downstream
AEMSwap content based on visitor state

Optiview observes and suggests. It does not render banners, replace your CMS, or require a new component library.

Example moments → experiences

Plain-language intent first. Expand any row for copy-ready implementation snippets.

Payment feels unclear on mobile

GTM
When
Visitor is rechecking financing and pace is slowing.
Experience could
Show simpler payment ranges and hold back aggressive pop-ups.

Show implementation →

GTM snippet
// Custom Event: si_personalization_signal
// Branch on canonical IDs — NOT labels in panels
if ({{DLV - si.context.traffic_source_type}} === 'paid_search'
  && {{DLV - si.commercial_signals.blocker_ids}}.includes('financing_or_payment_uncertainty')) {
  showFinancingReassuranceModule();
}
if ({{DLV - si.session_dynamics.decision_pace}} === 'slow') delayInterruption();

Serious comparison before deciding

React
When
Visitor keeps returning to the same finalists.
Experience could
Keep shortlist visible and highlight key differences only.

Show implementation →

React snippet
const cs = envelope?.si?.commercial_signals;
if (cs?.recommended_next_actions?.some(a => a.action_id === "support_comparison")) {
  return <ComparisonTray />;
}

Overwhelmed on mobile

GTM
When
Evening mobile visit with slowing pace.
Experience could
Delay interruptions; keep navigation calm.

Show implementation →

GTM snippet
// si.session_dynamics.decision_pace === 'slow'
// si.context.device_class === 'mobile'
// → delayInterruption() or hide sticky CTA

For builders — implementation examples

For engineers: the tag pushes si_personalization_signal with stable *_id fields to branch on — not human labels from the Live panel.

Example dataLayer payload
window.dataLayer.push({
  "event": "si_personalization_signal",
  "si": {
    "context": {
      "traffic_source_type": "paid_search",
      "device_class": "mobile",
      "visit_recency_bucket": "returning_30d"
    },
    "session_dynamics": {
      "decision_pace": "slow",
      "engagement_trend": "deepening"
    },
    "commercial_signals": {
      "status": "active",
      "commercial_state_id": "hesitating",
      "blocker_ids": [
        "financing_or_payment_uncertainty"
      ],
      "recommended_next_actions": [
        {
          "action_id": "promote_financing_clarity"
        }
      ]
    }
  }
});
Server / webhook
Server / webhook
POST /your/collector
{
  "event": "si_personalization_signal",
  "si": {
    "commercial_signals": {
      "status": "active",
      "commercial_state_id": "hesitating",
      "blocker_ids": ["financing_or_payment_uncertainty"],
      "recommended_next_actions": [{ "action_id": "promote_financing_clarity" }]
    }
  }
}
Browser event listener
Browser event listener
window.addEventListener("si:personalization-signal", (e) => {
  const cs = e.detail?.si?.commercial_signals;
  if (cs?.status !== "active") return;
  const actionId = cs.recommended_next_actions?.[0]?.action_id;
  if (cs.commercial_state_id === "hesitating" && actionId === "promote_financing_clarity") {
    // render your financing module
  }
});
Adobe Target
Adobe Target
// Profile parameters — use flat IDs from pushCommercialSignalsToTargetProfile
// si_commercial_state_id, si_blocker_ids (comma-separated), si_top_action_id
if ({{DLV - si.commercial_signals.commercial_state_id}} === 'hesitating') suppressPopup();

Full builder guide & field reference → · Install →