Competitor Show Tracker
SkillDev toolsRank upcoming events by competitor-name matches in Lensmor records, with explicit credit approval and coverage limits.
Use Competitor Show Tracker in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add Competitor Show Tracker and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the Competitor Show Tracker skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by lensmorofficial/trade-show-skills in competitor-show-tracker/SKILL.md and read by Ahel’s review.
Input a list of competitor company names and rank upcoming trade shows by how many names match Lensmor exhibitor records. Treat these as database matches, not independently verified attendance confirmations.
When this skill triggers:
- Run the API key check (Step 1) before any API call
- Call
POST /external/exhibitors/search-eventsonce per competitor company - Aggregate results by event, count distinct competitors per event
- Filter to future events only, then rank by competitor concentration
- Confirm estimated credit use and HubSpot activity logging before the first live call
Use Cases
- Show circuit mapping: Understand which events your competitive set treats as must-attend
- Counter-programming: Identify shows where multiple competitors cluster — decide whether to appear or deliberately avoid
- Budget prioritization: Focus booth investment on shows where your buyers and your competitors overlap
- Blind spot detection: Find shows where one key competitor dominates and you have no presence
Example Requests
- Which shows are my competitors at?
- 竞争对手去哪些展会
- Auf welchen Messen sind meine Wettbewerber?
- 競合他社の出展先は?
- ¿En qué ferias están mis competidores?
Request Handling
- Every Lensmor request, including event lookup and pagination, must send
Authorization: Bearer $LENSMOR_API_KEY. Send the key only tohttps://platform.lensmor.com; never include it in URLs, output, or requests to company/event websites. - Use a 10-second connection timeout and 30-second request timeout. Inspect the HTTP status before interpreting JSON; a non-2xx response, malformed JSON, or missing required response fields is a failed request, not an empty result or a zero score.
- Start with one page (
page=1,pageSizeat most 100). Preserve filters across pages and disclose partial coverage. Do not fetch every page automatically. - For a read-only GET, allow at most one retry after a 429 or temporary 5xx, respecting
Retry-After; if the delay is unavailable or impractical, report the failure and stop. Do not retry a POST automatically. A timeout may leave its outcome unknown, especially for a charged search. - If event lookup returns multiple editions, ask for the intended year/edition before continuing. Use the resolved event ID, never a sample ID from this document.
Workflow
Step 1: API Key Check
Before making any API call, verify the key is configured:
[ -n "${LENSMOR_API_KEY:-}" ] && echo "ok" || echo "missing"
If the result is missing, stop and respond:
The
LENSMOR_API_KEYenvironment variable is not set. This skill requires a Lensmor API key to look up exhibitor data. Configure an existing Lensmor API key in the agent environment; see the authentication documentation:export LENSMOR_API_KEY=your_key_here
Do not proceed to any API call until the key is confirmed present.
Step 2: Collect Inputs
Required:
competitors— list of company names (1–20 companies; comparative ranking needs at least two). Accept as a comma-separated list, bullet list, or inline prose.
Optional:
date_from— only include events on or after this date (ISO 8601, default: today)date_to— only include events on or before this date (e.g. restrict to next 12 months)pageSize— results per company lookup (default: 50; raise to 100 if the user wants broader coverage)
If the user provides one company name, run the same company-to-event lookup after cost approval and return an unranked event list. Do not redirect to cross-event exhibitor discovery: that endpoint returns companies rather than a company's associated events.
Trim names and deduplicate exact names case-insensitively before quoting the maximum cost and denominator. Keep aliases distinct unless the user confirms they refer to the same competitor. Validate date_from <= date_to and use the user's timezone for today's default cutoff.
Step 3: Confirm Cost and Activity Logging
For each request that returns at least one matching event, the current API:
- consumes 50 credits
- records an API search event
- asynchronously updates the API-key owner's HubSpot
last_search_date
An empty result does not consume credits. Each additional page is a separate request and can consume another 50 credits when it returns results.
Before calling the endpoint, state the maximum first-page cost as number of competitors × 50 credits and ask the user to approve both the credit use and HubSpot activity record. Do not proceed without confirmation.
Step 4: Fetch Events per Competitor
For each competitor in the list, call:
Endpoint: POST https://platform.lensmor.com/external/exhibitors/search-events
Authentication: Authorization: Bearer $LENSMOR_API_KEY
Include Content-Type: application/json and x-call-source: agent. These date filters are applied locally; do not send unsupported date_from / date_to request fields.
Request body:
{
"company_name": "Siemens",
"page": 1,
"pageSize": 50
}
Run one request per competitor. For N competitors, make N sequential calls so failures, costs, and rate limits remain attributable. Label each result set by the input company name before aggregating.
Response structure:
{
"total": 18,
"page": 1,
"pageSize": 50,
"totalPages": 1,
"hasMore": false,
"items": [
{
"id": "12740",
"eventId": "12740",
"name": "Hannover Messe 2026",
"nickname": null,
"description": "World's leading industrial trade show",
"url": "https://www.hannovermesse.de",
"dateStart": "2026-04-20",
"dateEnd": "2026-04-24",
"venue": "Hannover Exhibition Centre",
"city": "Hannover",
"region": "Lower Saxony",
"country": "Germany",
"attendeeCount": 130000,
"exhibitorCount": 4000,
"personnelCount": 8200,
"image": "https://cdn.lensmor.com/events/hannovermesse.jpg",
"dataSource": "official",
"matchedExhibitors": [
{ "id": "exh_siemens_ag", "companyName": "Siemens AG" }
]
}
]
}
Field reference:
| Field | Type | Notes |
|---|---|---|
eventId | string | Stable Lensmor event identifier — use as the deduplication key across competitor lookups |
name | string | Official show name |
dateStart / dateEnd | string (ISO 8601) | Use these to filter future events |
city / country | string | Show location |
exhibitorCount | integer | Count in the Lensmor event record, not an independently verified organizer total |
matchedExhibitors | array | Which specific entities were matched for this company name — may include subsidiaries |
Step 5: Aggregate Across Competitors
After collecting results for all N companies, aggregate by eventId:
- Deduplicate events across all N result sets using
eventIdas the key - Union the
matchedExhibitorsentries from all competitors per event - Count distinct competitors per event (count the number of input company names with at least one returned
matchedExhibitorrecord — not the count of entities, which may include subsidiaries) - Filter inclusively by start date:
date_from <= dateStart <= date_to, omitting the upper bound only whendate_tois absent. Missing or invalid dates go into an unassessed section, not the upcoming ranking - Sort by competitor count descending, then returned
exhibitorCountdescending (unknown counts last), then start date ascending. This tie-break is a display choice, not proof of business priority
Example aggregation logic (pseudocode):
event_map = {}
for each competitor C in input_list:
for each event E in results[C].items:
if E.dateStart is missing or invalid: record as unassessed; continue
if E.dateStart < date_from: continue
if date_to exists and E.dateStart > date_to: continue
if E.matchedExhibitors is empty: continue
if E.eventId not in event_map:
event_map[E.eventId] = { event: E, competitors_seen: {} }
event_map[E.eventId].competitors_seen[C] = E.matchedExhibitors
ranked = sort event_map.values() by competitor_count desc,
exhibitorCount desc (unknown last), dateStart asc
Step 6: Format the Output
Section 1 — Summary Header
## Competitor Show Tracker
**Competitors tracked**: [list of input company names]
**Date range**: [date_from] → [date_to or "open"]
**Unique upcoming events found**: [N]
**Events with 2+ competitors**: [N]
Section 2 — Ranked Event Table
## Events Ranked by Competitor Concentration
| Rank | Show | Dates | Location | Competitors | Exhibitors |
|------|------|-------|----------|-------------|------------|
| 1 | [Hannover Messe 2026](https://hannovermesse.de) | Apr 20–24, 2026 | Hannover, DE | 4 / 5 | 4,000 |
| 2 | [SPS 2026](https://sps.mesago.com) | Nov 2026 | Nuremberg, DE | 3 / 5 | 1,400 |
| 3 | [Automate 2026](https://automateshow.com) | Jun 2026 | Chicago, US | 2 / 5 | 600 |
"Competitors" column format: [matched count] / [total input count]
Section 3 — Event Detail Cards (for events with 2+ competitors)
For each event with 2 or more competitor names matched:
### Hannover Messe 2026 — 4 of 5 competitors matched
📅 Apr 20–24, 2026 · Hannover, Germany · 4,000 exhibitors
**Competitors matched in Lensmor exhibitor records:**
- **Siemens** → matched as: Siemens AG, Siemens Digital Industries
- **ABB** → matched as: ABB Ltd
- **Bosch** → matched as: Bosch Rexroth AG
- **Schneider Electric** → matched as: Schneider Electric SE
**No match in retrieved pages:** Rockwell Automation _(coverage may be incomplete; this does not prove absence)_
Section 4 — Insights
## Insights
- **Most contested show**: [event with highest competitor count] — [N/N] competitor names matched
- **Must-watch shows** (3+ competitors): [list]
- **Single-competitor shows**: [events where only 1 competitor appears — lower priority but monitor]
- **Gaps**: [input competitors with zero events found — may not be in Lensmor's database yet]
Error Handling
| HTTP Status | Meaning | Response |
|---|---|---|
| 401 | API key invalid or expired | "The API key was rejected. Verify LENSMOR_API_KEY or contact hello@lensmor.com." |
| 400 | Malformed request | "Request invalid for [company_name]. Verify the company name and retry." |
| 402 | Insufficient credits | Stop the run and report completed vs. unsearched competitors; do not retry or continue spending |
| 429 | Rate limit exceeded | Stop and report partial progress; do not automatically repeat the charged POST |
| 502 / 5xx | Server error | "The Lensmor API returned a server error for [company_name]. Skipping — results will note this company as incomplete." |
Empty items | No events found | Note in Insights section under "Gaps": this competitor returned no events and may not be in Lensmor's database. Do not omit silently. |
For every successful request, report whether credits were consumed. Compare GET /external/credits/balance before and after the run when available; label the difference as a balance change because concurrent activity can also affect it. If no request-level charge evidence is available, label the documented price as expected, not verified deduction. A timed-out POST has an unknown outcome: do not automatically resend it or claim no charge occurred.
Track each competitor as complete, partial (hasMore: true), failed, or not searched. Failed and unsearched competitors are not zero matches. State how many competitors were successfully searched alongside the original input denominator; rank only retrieved evidence and label a partial ranking clearly. Each extra page needs a remaining user-approved credit budget.
Follow-up Routing
| Outcome | Recommended next action |
|---|---|
| Top event identified, want to exhibit | Run trade-show-fit-score with the eventId |
| Want to find more companies at a specific show | Run trade-show-exhibitor-search with the event_id |
| Want contacts at a specific competitor | Run trade-show-contact-finder with the company name |
| Budget decision needed | Run trade-show-budget-planner for the top-ranked event |
| Want full competitor booth analysis | Run pre-show-competitor-analysis |
Output Rules
- All URLs formatted as
[text](url)— never bare links - Never output the value of
LENSMOR_API_KEY - Never expose endpoint paths, raw curl commands, or internal token values in the response
- Competitor count column format:
matched / total— never drop the denominator - Filter to future events by default; always state the date cutoff used in the summary header
- If a competitor returns no results, report it explicitly in Insights — never silently drop it
- Use
eventId(not event name) as the deduplication key — the same show may appear under slightly different names across competitor lookups matchedExhibitorsmay return subsidiaries or regional entities — group them under the input company name; list the specific matched entity names in the detail card- When
hasMore: truefor any competitor, note that results may be incomplete and offer to fetch additional pages - End every response with 1–3 follow-up suggestions based on the top-ranked events
- Call returned companies "matched in Lensmor exhibitor records", not "confirmed attendees" or independently verified exhibitors
- Report that successful searches update HubSpot
last_search_date
Quality Checks
Before delivering:
- Confirm that deduplication used
eventId, not event name — name variations across lookups would create false duplicates - Competitor count in the ranked table must reflect number of input companies with a returned match, not number of
matchedExhibitorentities (a single company may have multiple subsidiary matches) - Any competitor with no results must appear in the Insights "Gaps" section — do not omit
- Date filter must be applied before ranking — past events must not appear in the ranked output
- If one competitor was provided, return its event associations without inventing a comparative ranking
- Apply both date bounds, deduplicate input names before counting, and keep failed/partial lookups distinct from complete zero-result searches
Signals
- GitHub stars
- 48
- Forks
- 6
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
competitor-show-tracker- Source
- github.com/lensmorofficial/trade-show-skills
github.com/lensmorofficial/trade-show-skills
Related picks
Skill · larksuite
The pick for Markdownmarkdown-formatter
Skill · nvidia
The pick for Markdownhubspot
Skill · builderio
The pick for Hubspotprospecting
Skill · coreyhaines31
The pick for Companiesquantitative-screening
Skill · agentii-ai
The pick for Companiesaussenwirtschaft-bafa-genehmigungen-cbam-co2
Skill · klotzkette
The pick for Global