Skip to main content
Glama

get_event_stats

Analyze Meta Ads pixel event health with archetype-aware diagnostics. Evaluate coverage, parameter completeness, and flags to classify tracking status.

Instructions

Get event statistics with archetype-aware diagnostic analysis.

Checks event coverage, parameter completeness, diagnostic flags, and classifies overall tracking health.

Args: pixel_id: Pixel ID (numeric string). archetype: Account archetype for requirement matching: 'ecommerce', 'lead_gen', 'awareness', 'traffic', 'hybrid', 'messages'.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pixel_idYes
archetypeNohybrid

Implementation Reference

  • Main handler for get_event_stats tool: fetches pixel info, event stats, diagnostic checks, classifies health, and returns a full diagnostic summary.
    @mcp.tool()
    def get_event_stats(
        pixel_id: str,
        archetype: str = "hybrid",
    ) -> dict:
        """
        Get event statistics with archetype-aware diagnostic analysis.
    
        Checks event coverage, parameter completeness, diagnostic flags,
        and classifies overall tracking health.
    
        Args:
            pixel_id: Pixel ID (numeric string).
            archetype: Account archetype for requirement matching:
                'ecommerce', 'lead_gen', 'awareness', 'traffic', 'hybrid', 'messages'.
        """
        api_client._ensure_initialized()
    
        # 1. Get pixel info
        try:
            pixel_info = api_client.graph_get(
                f"/{pixel_id}",
                fields=["id", "name", "last_fired_time", "is_unavailable", "creation_time"],
            )
        except MetaAPIError as e:
            return {
                "pixel_id": pixel_id,
                "error": f"Could not read pixel: {e}",
                "health": "missing",
            }
    
        # 2. Get events (last 24h)
        events_found: list[str] = []
        event_counts: dict[str, int] = {}
        try:
            stats_result = api_client.graph_get(
                f"/{pixel_id}/stats",
                params={"aggregation": "event"},
            )
            for bucket in stats_result.get("data", []):
                for entry in bucket.get("data", []):
                    name = entry.get("value", "Unknown")
                    count = entry.get("count", 0)
                    event_counts[name] = event_counts.get(name, 0) + count
                    if name not in events_found:
                        events_found.append(name)
        except MetaAPIError:
            pass
    
        # 3. Get diagnostics (da_checks)
        diagnostics: list[dict] = []
        try:
            diag_result = api_client.graph_get(f"/{pixel_id}/da_checks")
            diagnostics = diag_result.get("data", [])
        except MetaAPIError:
            pass
    
        # 4. Classify health
        classification = _classify_pixel_health(pixel_info, events_found, archetype, diagnostics)
    
        # 5. Check value parameter coverage for purchase events
        value_coverage = None
        if "Purchase" in events_found or "purchase" in [e.lower() for e in events_found]:
            # We can't check individual event params via stats API alone,
            # but we can flag it as needing verification
            value_coverage = {
                "event": "Purchase",
                "has_value_param": "unknown_from_stats_api",
                "note": "Verify via Test Events or Events Manager that Purchase events include value and currency params.",
            }
            # Check if any da_check flags missing params
            for diag in diagnostics:
                if "missing_param" in diag.get("key", ""):
                    value_coverage["has_value_param"] = "likely_missing"
                    value_coverage["diagnostic"] = diag.get("description")
    
        # 6. Build summary
        diagnostic_summary = {
            "pixel_id": pixel_id,
            "pixel_name": pixel_info.get("name"),
            "last_fired": pixel_info.get("last_fired_time"),
            "is_unavailable": pixel_info.get("is_unavailable", False),
            "health": classification["health"],
            "archetype": archetype,
            "events_detected": events_found,
            "event_counts": dict(sorted(event_counts.items(), key=lambda x: x[1], reverse=True)),
            "total_events_24h": sum(event_counts.values()),
            "issues": classification["issues"],
            "issue_count": classification["issue_count"],
            "critical_issues": classification["critical_count"],
            "diagnostics_checked": len(diagnostics),
            "diagnostics_failed": sum(1 for d in diagnostics if d.get("result") == "failed"),
            "value_coverage": value_coverage,
            "rate_limit_usage_pct": api_client.rate_limits.max_usage_pct,
        }
    
        return diagnostic_summary
  • Input schema: pixel_id (str) and archetype (str, default 'hybrid') defining the tool's interface.
    @mcp.tool()
    def get_event_stats(
        pixel_id: str,
        archetype: str = "hybrid",
    ) -> dict:
        """
        Get event statistics with archetype-aware diagnostic analysis.
    
        Checks event coverage, parameter completeness, diagnostic flags,
        and classifies overall tracking health.
    
        Args:
            pixel_id: Pixel ID (numeric string).
            archetype: Account archetype for requirement matching:
                'ecommerce', 'lead_gen', 'awareness', 'traffic', 'hybrid', 'messages'.
        """
  • Registration via @mcp.tool() decorator that registers get_event_stats as an MCP tool.
    @mcp.tool()
  • Helper function called by get_event_stats to classify pixel health based on events found, archetype requirements, and diagnostics.
    def _classify_pixel_health(
        pixel_info: dict,
        events_found: list[str],
        archetype: str,
        diagnostics: list[dict],
    ) -> dict:
        """
        Classify overall pixel health based on info, events, and archetype requirements.
    
        Returns health classification with severity-ranked issues.
        """
        issues = []
        last_fired = pixel_info.get("last_fired_time")
        is_unavailable = pixel_info.get("is_unavailable", False)
    
        # Check pixel existence and availability
        if is_unavailable:
            issues.append({
                "severity": SEVERITY_CRITICAL,
                "check": "pixel_available",
                "message": "Pixel is marked as unavailable",
                "fix": "Check pixel configuration in Events Manager. May need re-creation.",
            })
    
        # Check last fired time
        if not last_fired:
            issues.append({
                "severity": SEVERITY_CRITICAL,
                "check": "pixel_ever_fired",
                "message": "Pixel has never fired",
                "fix": "Install pixel on website. Verify base code is on all pages.",
            })
            health = "never_fired"
        else:
            # Parse last fired and check recency
            try:
                fired_dt = datetime.fromisoformat(last_fired.replace("+0000", "+00:00").replace("Z", "+00:00"))
                now = datetime.now(timezone.utc)
                hours_since = (now - fired_dt).total_seconds() / 3600
    
                if hours_since > 48:
                    issues.append({
                        "severity": SEVERITY_HIGH,
                        "check": "pixel_recency",
                        "message": f"Pixel last fired {hours_since:.0f}h ago (> 48h)",
                        "fix": "Verify website is up and pixel code is still installed.",
                    })
            except (ValueError, TypeError):
                pass
    
            health = "healthy"  # Will be downgraded below if needed
    
        # Check required events by archetype
        reqs = REQUIRED_EVENTS.get(archetype, REQUIRED_EVENTS["hybrid"])
        events_lower = [e.lower() for e in events_found]
    
        missing_critical = []
        for ev in reqs["critical"]:
            if ev.lower() not in events_lower:
                missing_critical.append(ev)
    
        missing_important = []
        for ev in reqs["important"]:
            if ev.lower() not in events_lower:
                missing_important.append(ev)
    
        if missing_critical:
            issues.append({
                "severity": SEVERITY_CRITICAL,
                "check": "required_events",
                "message": f"Missing critical events for {archetype}: {', '.join(missing_critical)}",
                "fix": f"Install {', '.join(missing_critical)} event(s) on the website. For ecommerce, ensure purchase event fires on order confirmation page with value and currency params.",
            })
            if health != "never_fired":
                health = "degraded"
    
        if missing_important:
            issues.append({
                "severity": SEVERITY_MEDIUM,
                "check": "important_events",
                "message": f"Missing important events for {archetype}: {', '.join(missing_important)}",
                "fix": f"Add {', '.join(missing_important)} event(s) for better optimization data.",
            })
            if health == "healthy":
                health = "partial"
    
        # Check diagnostics from da_checks
        for diag in diagnostics:
            result = diag.get("result", "")
            if result == "failed":
                issues.append({
                    "severity": SEVERITY_HIGH,
                    "check": f"da_check_{diag.get('key', 'unknown')}",
                    "message": diag.get("description", diag.get("title", "Diagnostic check failed")),
                    "fix": diag.get("action_uri", "Check Events Manager for details."),
                })
                if health == "healthy":
                    health = "degraded"
    
        # If no events at all but pixel fired, it's degraded
        if not events_found and last_fired:
            if health == "healthy":
                health = "degraded"
    
        # Sort issues by severity
        severity_order = {SEVERITY_CRITICAL: 0, SEVERITY_HIGH: 1, SEVERITY_MEDIUM: 2, SEVERITY_LOW: 3, SEVERITY_INFO: 4}
        issues.sort(key=lambda x: severity_order.get(x["severity"], 5))
    
        return {
            "health": health,
            "issues": issues,
            "issue_count": len(issues),
            "critical_count": sum(1 for i in issues if i["severity"] == SEVERITY_CRITICAL),
            "events_detected": events_found,
            "archetype": archetype,
        }
  • Helper constants used by get_event_stats: archetype event requirements, value-required events, and severity level definitions.
    REQUIRED_EVENTS = {
        "ecommerce": {
            "critical": ["Purchase"],
            "important": ["AddToCart", "InitiateCheckout", "ViewContent"],
            "optional": ["ViewCategory", "Search", "AddPaymentInfo"],
        },
        "lead_gen": {
            "critical": ["Lead"],
            "important": ["SubmitApplication", "Contact"],
            "optional": ["ViewContent", "Schedule"],
        },
        "awareness": {
            "critical": [],
            "important": ["PageView"],
            "optional": ["ViewContent"],
        },
        "traffic": {
            "critical": [],
            "important": ["PageView", "ViewContent"],
            "optional": ["Lead"],
        },
        "hybrid": {
            "critical": ["Purchase", "Lead"],
            "important": ["AddToCart", "ViewContent", "InitiateCheckout"],
            "optional": ["SubmitApplication", "Contact"],
        },
        "messages": {
            "critical": [],
            "important": ["PageView"],
            "optional": ["Lead", "Contact"],
        },
    }
    
    # Events that require value/currency parameters
    VALUE_REQUIRED_EVENTS = ["Purchase"]
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden. It states it checks diagnostic flags and classifies health but does not disclose whether the operation is read-only, side effects, error behavior, or limitations. The behavioral disclosure is incomplete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise: two short paragraphs and an Args list. Every sentence adds value, and the purpose is front-loaded. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description lacks details about return values or error handling. It explains input well but fails to specify what the output looks like, which is necessary for a diagnostic tool. Adequate but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so description must compensate. It adds semantic value by clarifying pixel_id is a 'numeric string' and listing archetype values ('ecommerce', 'lead_gen', etc.) beyond the schema's default-only indication. However, it could be more precise about pixel_id format.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'get' and resource 'event statistics' with the specific qualifier 'archetype-aware diagnostic analysis'. It differentiates from siblings like 'get_pixel_events' (likely raw events) and 'run_tracking_diagnostic' by focusing on coverage, completeness, and classification.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives like 'get_pixel_events' or 'run_tracking_diagnostic'. The description does not mention when-not-to-use or provide context for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/brandu-mos/konquest-meta-ads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server