mattrguerra/meridian-skillsmainPrivate on GitHub, published here in full

bitrix-pipeline-board/

Bitrix Pipeline Board

Turn the open Bitrix pipeline into one interactive board: a stacked bar of leads-per-owner, owner and stage filters, and a table where every row links straight to the lead in Bitrix. End with the analytical read, not just the picture.

Constants

  • Bitrix lead link base: https://meridian.bitrix24.example/crm/lead/details/{id}/
  • Deal link base (if running on deals): https://meridian.bitrix24.example/crm/deal/details/{id}/
  • Active CS / sales owners (for orphan detection): Matt Guerra, Hazel Okafor, Marco Ibáñez, Ines Carvalho, Theo Bassett.
  • Known former owner to flag: Owen Pryce. Any lead still assigned to him is orphaned, so surface it.

Workflow

1. Pull the stage map and counts

Load the Bitrix tools (tool_search for "bitrix pipeline summary leads stages"), then call pipeline_summary with entity_type=lead, scope=open. This returns every stage with its human name, internal stage ID, and exact count. The grand total is the headline number. Don't hardcode stage IDs from this skill. Read them fresh each run, since stages get renamed and added.

2. Scale guard: check the total before enumerating

This board enumerates every record and links every row, which only works at lead scale (hundreds). Look at the pipeline_summary grand total first. If it's more than ~400 records, or spans multiple pipelines/categories, do not fan out and render every row: you'll trigger dozens of paginated pulls and an unusable table. Instead either (a) ask which pipeline/stage to scope to, or (b) drop to counts-only mode: build the owner×stage bar from pipeline_summary called once per owner (assigned_to=<name>), with no per-record table or links. The open lead funnel normally sits in the hundreds, so leads almost always take the full path; deals usually do not (see the deal section).

3. Pull the records in each non-zero stage

For every stage with count > 0, call list_records with entity_type=lead, stage=<stage ID>, limit=50. The summary line for each lead exposes the owner as @Owner Name; that is where the assignee comes from. Parse out lead ID (the [#####]), title, and owner.

Reconcile: the sum of your per-stage pulls must equal the pipeline_summary total. State the arithmetic so it's checkable.

50-cap caveat: stage-filtered list_records (no date filter) caps at 50 rows. If pipeline_summary shows a stage over 50, that one pull truncates. Work around it by splitting that stage with created_from/created_to date windows (date-filtered queries auto-paginate to 200) and stitching the results, or by pulling that stage per-owner. Flag it if you hit it.

4. Bucket each lead into a stage group

Three groups drive the chart and the row badges. Classify by stage name, not a frozen ID list:

  • intake: pre-work stages: New/Unassigned, Assigned.
  • parked: Parked, and any holding / "need to sort" stage.
  • active: everything else open (First Reply, Client Replied, Need Follow Up, Waiting For Client, No Reply, Reorder in Progress, Consultation Scheduled, Quote Sent, Quote Approved, etc.).

5. Render the board

Load the visualizer guidance (read_me with modules ["interactive","chart"]), then build the widget using references/widget-template.html as the scaffold. Drop the parsed leads into the D array and let the script compute the per-owner stacked bar and build the filterable table. The chart is a horizontal stacked bar (owners on the y-axis, intake/active/parked segments). The table row links each lead ID to the Bitrix base + id.

6. Give the read, not just the chart

A board nobody acts on is wallpaper. After the widget, surface in prose whatever is actually true this run:

  • Owner concentration: if one rep holds a lopsided share (e.g. >60%), name it and the risk (bottleneck / single point of failure if they're out).
  • Orphaned leads: any lead owned by a former employee (Owen Pryce) or sitting unassigned; recommend reassign or kill.
  • Parked backlog: how big the parked block is relative to active; if parked is the largest single bucket, flag it for a sweep (dead vs. neglected).
  • Thin back end: call out if the late stages (Quote Sent / Quote Approved) are near-empty while replies pile up earlier.

Keep it to what the numbers support. Don't manufacture a finding that isn't there.

Running on deals: read this first

Deals are NOT a bigger version of leads. The open deal set is far larger and spans many separate pipelines/categories (orders, production, fulfillment, LinkedIn outreach, partner outreach, etc.), and includes terminal-ish stages like "Order Delivered" that hold large numbers of fulfilled orders and are not "in progress" in any pipeline sense. The lead approach (enumerate every record, link every row, bucket into intake/active/parked) does not transfer.

So for deals:

  • Never enumerate all open deals. The scale guard in step 2 applies hard here.
  • Make Matt scope it to one pipeline/category or a specific stage before building anything ("which deal pipeline: orders, the sales/LinkedIn funnel, production?"). A board only makes sense within one funnel.
  • Once scoped to a single pipeline of manageable size, run the same flow with entity_type=deal, the deal link base, and an intake/active/parked (or stage-appropriate) classification for that pipeline's stages.
  • If the scoped set is still large or links aren't needed, use counts-only mode: pipeline_summary(deal, open) for the stage counts, called per owner for the owner split, rendered as the stacked bar with no per-record table.

scope=open is still required (won/lost are out of scope).