
Influencer Tracking
- 59 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Measure influencer ROI with per-creator UTM links and unique discount codes to attribute sales against campaign spend.
About
Combines UTM links for web traffic with unique discount codes for purchase attribution to reliably track influencer campaigns. A developer uses it to prove influencer ROI or separate organic from paid post attribution.
- Uses UTMs and discount codes together for cross-device attribution
- Per-creator link setup and platform performance comparison
Influencer Tracking by the numbers
- 59 all-time installs (skills.sh)
- Ranked #1,285 of 1,879 Marketing & SEO skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill influencer-trackingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 59 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Measure influencer ROI with per-creator UTM links and unique discount codes to attribute sales against campaign spend.
Files
Influencer Tracking
Overview
Influencer marketing drives significant revenue but is notoriously difficult to attribute because customers often see a post, leave the platform, and purchase days later through a direct or organic channel. The solution is using both UTM links (for web traffic) and unique discount codes (for purchase attribution) together — these two signals complement each other and provide reliable attribution across devices. Most of this setup requires no custom code.
Note: For full influencer campaign management (discovery, briefs, deliverables), see @influencer-marketplace-integration. This skill focuses purely on attribution and analytics.
When to Use This Skill
- When managing 10+ influencer partnerships and tracking them in a spreadsheet
- When needing to prove ROI of influencer spend to leadership with first-party data
- When running gifting campaigns and needing to separate organic versus paid post attribution
- When comparing performance across platforms (Instagram, TikTok, YouTube) in a single dashboard
Core Instructions
Step 1: Set up UTM links for each creator
Create a unique UTM link for every influencer and campaign combination. Use Google's Campaign URL Builder at ga-dev-tools.google.com/campaign-url-builder:
| UTM Parameter | Value | Example |
|---|---|---|
utm_source | Social platform | instagram, tiktok, youtube |
utm_medium | Always influencer | influencer |
utm_campaign | Campaign name | spring-2026, black-friday |
utm_content | Creator handle | janedoe, johndoe_fitness |
Example URL: yourstore.com/?utm_source=instagram&utm_medium=influencer&utm_campaign=spring-2026&utm_content=janedoe
Shorten the link for Instagram bio use: use Bitly or a custom short domain. Store the mapping between short URL and UTM parameters in a spreadsheet.
Important: give influencers the shortened link and instruct them to place it in their link-in-bio, not in the post caption (Instagram captions do not have clickable links).
Step 2: Create unique discount codes for each creator
Discount codes capture purchases that happen via direct/organic after the initial influencer visit — the UTM link alone misses these.
---
Shopify
1. Go to Shopify Admin → Discounts → Create Discount → Amount off order 2. Configure:
- Discount code:
JANEDOE15(creator handle + percentage) - Discount type: Percentage — 15%
- Applies to: All products (or specific collections if needed)
- Minimum purchase requirement: $30 (to ensure positive ROI)
- Usage limits: Enable "Limit to one use per customer"
- Active dates: Set campaign start and end date
3. Click Save and send the code to the influencer
Pro tip: Use Shopify Flow (Plus) or an app like Glew to automatically tag orders using a specific discount code with the influencer's name — this makes attribution reporting easier.
---
WooCommerce
1. Go to WooCommerce → Marketing → Coupons → Add coupon 2. Configure:
- Coupon code:
JANEDOE15 - Discount type: Percentage discount — 15%
- Minimum spend: $30
- Usage limit per user: 1
- Coupon expiry date: Campaign end date
3. Under Restrictions → Allowed emails: optionally limit to new customers only
---
BigCommerce
1. Go to BigCommerce Admin → Marketing → Promotions → Create Promotion 2. Set coupon code, discount amount, and usage limits 3. Set an expiry date matching the campaign end date
---
Step 3: Track attribution in Google Analytics 4
For all platforms, UTM tracking works through GA4 automatically:
1. In GA4 → Reports → Acquisition → Traffic Acquisition: filter by Session medium = influencer to see all influencer-driven sessions 2. In GA4 → Reports → Acquisition → Traffic Acquisition: add Session campaign as a secondary dimension to compare by campaign 3. In GA4 → Explore → Free Form: build a report with utm_content as a dimension to compare creator performance
See influencer-attributed revenue: 1. Go to GA4 → Reports → Monetization → Ecommerce Purchases 2. Filter by utm_medium = influencer 3. Add utm_content as a dimension to see revenue per creator
Step 4: Track discount code revenue
---
Shopify
1. Go to Shopify Admin → Analytics → Reports → Discounts → Discount codes 2. Filter by creator-specific codes to see revenue, order count, and usage per influencer 3. For a comparison view: Analytics → Custom Reports → Orders → group by discount code
---
WooCommerce
1. Go to WooCommerce → Analytics → Coupons 2. Filter by influencer-specific coupon codes to see revenue and orders 3. Or install Metorik ($50/mo) for more advanced coupon attribution reporting
---
Step 5: Build a creator performance tracker
Combine UTM revenue (from GA4) and discount code revenue (from Shopify/WooCommerce) in a single tracking spreadsheet:
| Creator | Platform | Campaign | UTM Revenue | Code Revenue | Total Revenue | Cost | ROAS |
|---|---|---|---|---|---|---|---|
| @janedoe | Spring 2026 | $840 | $1,200 | $2,040 | $500 | 4.1x | |
| @johndoe | TikTok | Spring 2026 | $320 | $680 | $1,000 | $300 | 3.3x |
ROAS calculation: Total Revenue ÷ Campaign Cost (flat fee + COGS of gifted product + commission paid)
Normalize by reach for fair comparison between micro and macro influencers:
- Revenue per 1,000 followers = Total Revenue / (Follower Count / 1,000)
- This metric often reveals that micro-influencers outperform macro-influencers significantly
Step 6: For headless stores — capture first-touch attribution
Standard last-click UTM attribution in GA4 misses influencer impact. Capture first-touch UTM data server-side:
// On page load, store the first UTM touch in a session cookie
function captureFirstTouchUTM() {
const params = new URLSearchParams(window.location.search);
if (!params.get('utm_source')) return;
// Only store if no first-touch already captured this session
if (!sessionStorage.getItem('first_touch_utm')) {
sessionStorage.setItem('first_touch_utm', JSON.stringify({
utm_source: params.get('utm_source'),
utm_medium: params.get('utm_medium'),
utm_campaign: params.get('utm_campaign'),
utm_content: params.get('utm_content'),
landed_at: new Date().toISOString(),
}));
}
}
// At checkout, include first-touch UTM in the order metadata
// Store in your order database for reportingBest Practices
- Always use both UTM links and promo codes — UTM tracks web traffic; codes capture purchases that happen days later via direct or organic
- Use `utm_content` for the influencer handle — this lets you compare performance by creator within a single campaign (e.g., 20 influencers in the same spring campaign)
- For Instagram, links must go in bio — give influencers a link-in-bio URL and tell them to reference "link in bio" in their caption; caption links are not clickable
- Set campaign end dates on promo codes — expires influencer discounts automatically and prevents long-term code sharing on coupon sites
- Track gifting value as campaign cost — gifted products have COGS; include this in your ROAS calculation
- Compare EMV (Earned Media Value) alongside revenue — high-reach posts with lower conversion may still justify spend as brand awareness
Common Pitfalls
| Problem | Solution |
|---|---|
| Promo codes shared on coupon/deal sites | Add per-customer usage limit (1 per customer) and monitor daily usage velocity for spikes |
| UTM attribution lost when customer uses a different device | Supplement UTM tracking with promo codes as a device-agnostic signal |
| No way to compare micro-influencers vs. macro-influencers fairly | Calculate revenue per 1,000 followers (normalized RPM) to compare across follower counts |
| Influencer posts after campaign end date | Add a 7-day grace period to your code expiry; store first_attributed_order_at to detect late posts |
| GA4 shows organic instead of influencer for returning customers | Use first-touch attribution model in GA4 Explore or compare against discount code data |
Related Skills
- @influencer-marketplace-integration
- @affiliate-program
- @marketing-attribution-dashboard
- @social-commerce
- @ugc-campaign-management
{
"context": "Tests whether the agent calculates campaign ROI metrics using the correct formulas (ROAS, CPS, EMV at $0.01/impression, RPM), treats gifted campaign budgets as real spend, uses EMV as a secondary metric in narrative, and handles edge cases like zero-budget or zero-order campaigns.",
"type": "weighted_checklist",
"checklist": [
{
"name": "ROAS formula",
"max_score": 10,
"description": "roas is calculated as total attributed revenue divided by campaign budget (revenue / budget), not as a percentage or inverted"
},
{
"name": "CPS formula",
"max_score": 10,
"description": "cps is calculated as campaign budget divided by number of attributed orders (budget / ordersCount)"
},
{
"name": "EMV formula",
"max_score": 12,
"description": "emv is calculated as impressions multiplied by 0.01 (the $0.01-per-impression industry rate), not a different rate"
},
{
"name": "Gifted budget included",
"max_score": 12,
"description": "Campaigns with feeStructure 'gifted' (camp-003, camp-005) use their budget value as real spend in ROAS and CPS calculations, NOT treated as zero-cost"
},
{
"name": "RPM calculated",
"max_score": 12,
"description": "rpm (revenue per 1,000 followers) is present in campaign-report.json and computed as (revenue / followerCount) * 1000"
},
{
"name": "Null on zero-division",
"max_score": 8,
"description": "roas and cps are null (not NaN, Infinity, or 0) when budget or ordersCount is zero"
},
{
"name": "EMV as secondary metric",
"max_score": 10,
"description": "summary.md explicitly uses EMV as a secondary consideration when discussing campaigns with low direct conversion (not just mentioned — referenced in the narrative interpretation)"
},
{
"name": "Both attribution types summed",
"max_score": 8,
"description": "attributedRevenue (or equivalent total) in campaign-report.json sums orders from both 'promo_code' and 'utm_first_touch' attributionType values"
},
{
"name": "AOV calculated",
"max_score": 8,
"description": "aov (average order value) is present and calculated as revenue / ordersCount"
},
{
"name": "Revenue in dollars",
"max_score": 10,
"description": "Revenue figures in campaign-report.json are in dollars (not cents) — subtotalCents values are divided by 100"
}
]
}
Post-Campaign ROI Report Generator
Problem/Feature Description
A consumer goods brand ran five influencer campaigns over the past quarter — a mix of paid partnerships and gifted product collaborations across micro- and macro-influencers. The head of growth needs a clear picture of which campaigns and influencers actually delivered ROI so she can decide where to invest next season.
The team has exported raw campaign and order data. They need a script that processes this data and produces a structured performance report. The report should go beyond simple revenue totals: it needs metrics that account for the cost of gifted product (not just cash fees), allow fair comparison between an influencer with 800K followers and one with 12K, and include an estimate of the brand-awareness value generated even when direct sales were low. The output should be in a format the growth team can read directly or pass into a spreadsheet.
Output Specification
Produce a Python or TypeScript script roi-report.ts (or roi-report.py) that:
- Reads the input data files below
- Computes per-campaign metrics and outputs
campaign-report.json
campaign-report.json should be an array of campaign result objects, one per campaign, each containing at minimum:
campaignId,influencerHandle,platform,followerCountbudget,revenue,ordersCount,aovroas,cpsimpressions,emvrpm(revenue per 1,000 followers)attributedRevenue(from both promo code and UTM-attributed orders)
Also produce a summary.md that ranks the campaigns by a metric of your choice and includes a brief (3–5 sentence) narrative interpretation that uses EMV as a secondary consideration for campaigns with low direct conversion.
Input Files
Extract these files before beginning.
=============== FILE: inputs/campaigns.json =============== [ { "id": "camp-001", "name": "Winter Warmth", "influencerId": "inf-A", "influencerHandle": "@naturalnora", "platform": "instagram", "followerCount": 820000, "budget": 8000, "feeStructure": "flat_fee", "impressions": 410000 }, { "id": "camp-002", "name": "Clean Kitchen", "influencerId": "inf-B", "influencerHandle": "@kitchenbyalex", "platform": "tiktok", "followerCount": 95000, "budget": 1200, "feeStructure": "flat_fee", "impressions": 280000 }, { "id": "camp-003", "name": "Morning Ritual", "influencerId": "inf-C", "influencerHandle": "@risewithreena", "platform": "instagram", "followerCount": 14000, "budget": 350, "feeStructure": "gifted", "impressions": 9800 }, { "id": "camp-004", "name": "Eco Everyday", "influencerId": "inf-D", "influencerHandle": "@ecowithjamie", "platform": "youtube", "followerCount": 210000, "budget": 3500, "feeStructure": "flat_fee", "impressions": 67000 }, { "id": "camp-005", "name": "Gifted Glow", "influencerId": "inf-E", "influencerHandle": "@glowingwithgrace", "platform": "instagram", "followerCount": 38000, "budget": 180, "feeStructure": "gifted", "impressions": 22000 } ] =============== FILE: inputs/orders.json =============== [ { "orderId": "ord-001", "campaignId": "camp-001", "subtotalCents": 8900, "attributionType": "utm_first_touch" }, { "orderId": "ord-002", "campaignId": "camp-001", "subtotalCents": 6500, "attributionType": "promo_code" }, { "orderId": "ord-003", "campaignId": "camp-001", "subtotalCents": 11200, "attributionType": "utm_first_touch" }, { "orderId": "ord-004", "campaignId": "camp-002", "subtotalCents": 5400, "attributionType": "promo_code" }, { "orderId": "ord-005", "campaignId": "camp-002", "subtotalCents": 7800, "attributionType": "promo_code" }, { "orderId": "ord-006", "campaignId": "camp-002", "subtotalCents": 4200, "attributionType": "utm_first_touch" }, { "orderId": "ord-007", "campaignId": "camp-002", "subtotalCents": 9100, "attributionType": "promo_code" }, { "orderId": "ord-008", "campaignId": "camp-003", "subtotalCents": 3300, "attributionType": "promo_code" }, { "orderId": "ord-009", "campaignId": "camp-003", "subtotalCents": 2800, "attributionType": "utm_first_touch" }, { "orderId": "ord-010", "campaignId": "camp-004", "subtotalCents": 14500, "attributionType": "utm_first_touch" }, { "orderId": "ord-011", "campaignId": "camp-004", "subtotalCents": 9800, "attributionType": "promo_code" }, { "orderId": "ord-012", "campaignId": "camp-005", "subtotalCents": 4100, "attributionType": "promo_code" } ]
{
"context": "Tests whether the agent implements first-touch UTM attribution correctly using sessionStorage vs. localStorage, handles the promo-code-first attribution priority, stores the correct attributionType, and captures both first-touch and last-touch data in the order record.",
"type": "weighted_checklist",
"checklist": [
{
"name": "sessionStorage for first-touch",
"max_score": 12,
"description": "client-attribution.js stores the first-touch UTM data in sessionStorage (not localStorage or a cookie)"
},
{
"name": "First-touch not overwritten",
"max_score": 12,
"description": "client-attribution.js checks whether first_touch_utm already exists in sessionStorage before writing; does NOT overwrite an existing first-touch"
},
{
"name": "localStorage for last-touch",
"max_score": 8,
"description": "client-attribution.js always updates last-touch UTM in localStorage on every page load with a UTM parameter present"
},
{
"name": "landed_at in first-touch",
"max_score": 8,
"description": "The first-touch record stored in sessionStorage includes a landed_at timestamp (ISO string)"
},
{
"name": "landing_page in first-touch",
"max_score": 8,
"description": "The first-touch record stored in sessionStorage includes landing_page (the URL pathname)"
},
{
"name": "Promo code attribution first",
"max_score": 12,
"description": "server-attribution.ts checks for a promo code and looks up its campaignId BEFORE checking UTM data"
},
{
"name": "UTM fallback condition",
"max_score": 10,
"description": "server-attribution.ts only falls back to UTM when no campaignId was found via promo code AND the first-touch utm_medium is exactly 'influencer'"
},
{
"name": "attributionType field",
"max_score": 10,
"description": "The attribution record includes an attributionType field set to 'promo_code' when attributed via promo code, and 'utm_first_touch' when attributed via UTM"
},
{
"name": "Both UTM touches stored",
"max_score": 10,
"description": "The attribution record in server-attribution.ts stores both firstTouchUtm and lastTouchUtm fields"
},
{
"name": "Attribution notes",
"max_score": 10,
"description": "ATTRIBUTION_NOTES.md explains that promo code attribution takes precedence over UTM and the reason why (device-agnostic / handles return visits)"
}
]
}
Influencer Attribution — Client & Server Implementation
Problem/Feature Description
A fashion e-commerce startup has been running influencer campaigns but their analytics show nearly zero attributed revenue because they only use last-click attribution. The real purchase path for influencer-driven customers typically looks like this: a user taps an Instagram story link, browses, leaves, and returns two days later directly to buy. By that point, the UTM parameters are gone and the influencer gets no credit.
The engineering team needs two pieces of code: a client-side JavaScript snippet that runs on every page load to reliably capture the initial influencer visit, and a server-side TypeScript function that runs at checkout to attribute the order to the correct influencer campaign. The attribution logic must handle the case where the customer used a promo code (which may have come from a different influencer than the one they clicked) and the case where they never used a code at all.
Output Specification
Produce two files:
1. client-attribution.js — A browser-side script (plain JS, no build step) with a function that should be called on every page load. The function reads URL query parameters and persists UTM data in browser storage so that it remains available at checkout time, even if the customer navigates away and returns later.
2. server-attribution.ts — A TypeScript module exporting an async function captureOrderInfluencerAttribution(orderId, request) that runs at order placement. It should resolve which influencer campaign deserves credit and write an attribution record. Include a db stub object and a type for the request so the file is self-contained and illustrates the logic clearly.
Add a ATTRIBUTION_NOTES.md explaining the attribution strategy — which signals are used, how conflicts between them are resolved, and why this approach handles multi-session purchase journeys correctly.
{
"context": "Tests whether the agent generates UTM tracking links and promo codes following the skill's conventions: correct UTM parameter naming, promo code format, promo code settings (per-customer limits, expiry), and metadata storage.",
"type": "weighted_checklist",
"checklist": [
{
"name": "utm_medium value",
"max_score": 10,
"description": "The tracking link contains utm_medium=influencer (exact string, not 'social' or 'paid' or similar)"
},
{
"name": "utm_source is platform",
"max_score": 8,
"description": "utm_source is set to the influencer's platform (e.g. 'instagram'), not a generic value"
},
{
"name": "utm_campaign normalized",
"max_score": 8,
"description": "utm_campaign is the campaign name lowercased with spaces replaced by hyphens (e.g. 'spring-glow')"
},
{
"name": "utm_content is handle",
"max_score": 10,
"description": "utm_content is the influencer handle with the '@' symbol removed (e.g. 'glowwithsophie'), not the full handle or any other identifier"
},
{
"name": "Promo code format",
"max_score": 12,
"description": "Each promo code is formed from the first 6 characters of the handle (uppercased, '@' removed) followed by the discount percentage as a number (e.g. GLOWWI15)"
},
{
"name": "Per-customer limit",
"max_score": 10,
"description": "The promo code configuration sets perCustomerLimit to 1 (one use per customer)"
},
{
"name": "Unlimited total usage",
"max_score": 8,
"description": "The promo code configuration sets usageLimit to null (not a finite number)"
},
{
"name": "Promo code expiry",
"max_score": 8,
"description": "The promo code's validUntil (or equivalent expiry field) is set to the campaign end date"
},
{
"name": "Promo metadata",
"max_score": 8,
"description": "The promo code configuration includes a metadata object containing both campaignId and influencerId"
},
{
"name": "Both artifacts per influencer",
"max_score": 8,
"description": "output.json contains both a trackingLink and a promoCode for each of the three influencers"
},
{
"name": "Promo details file",
"max_score": 10,
"description": "promo-details.json exists and contains full promo code configuration objects for each influencer"
}
]
}
Influencer Campaign Onboarding — Tracking Artifacts Generator
Problem/Feature Description
A direct-to-consumer skincare brand is scaling its influencer program from ad-hoc spreadsheet management to a structured, code-driven workflow. The marketing ops team has signed three influencers for a "Spring Glow" launch campaign running April 1–30, 2026. Each influencer needs a unique set of campaign tracking artifacts before they can post: a personalized tracking URL to their product page and a unique discount code to share with their audience.
The team needs a TypeScript module that takes an influencer roster and campaign configuration and produces the tracking link and promo code for each influencer. The module should follow the brand's internal conventions for UTM parameter naming and promo code formatting so that downstream analytics pipelines can parse them correctly.
Output Specification
Produce a TypeScript file influencer-onboarding.ts that:
- Defines the necessary data types/interfaces for influencers, campaigns, and UTM parameters
- Implements a function to build a UTM-tracked URL for a given influencer and campaign
- Implements a function to generate (and optionally "create") a promo code for a given influencer and campaign
- Exports a main function or script that processes the three influencers below and writes a JSON summary to
output.jsonwith each influencer's handle, tracking link, and promo code
The output.json file should be an array of objects, one per influencer, with at minimum the fields: handle, trackingLink, promoCode.
Also produce a promo-details.json file listing the full promo code configuration for each influencer (all fields that would be passed to the database/promotions system).
Input Files
The following data describes the campaign and influencer roster. Extract it before beginning.
=============== FILE: inputs/campaign.json =============== { "id": "camp-spring-2026", "name": "Spring Glow", "platform": "instagram", "startDate": "2026-04-01", "endDate": "2026-04-30", "budget": 4500, "discountPct": 15, "deliverables": ["1 feed post", "2 stories"], "destination": "/collections/spring" } =============== FILE: inputs/influencers.json =============== [ { "id": "inf-001", "handle": "@glowwithsophie", "platform": "instagram", "followerCount": 85000, "niche": ["skincare", "wellness"], "email": "sophie@example.com", "feeStructure": "flat_fee" }, { "id": "inf-002", "handle": "@thetaradiaries", "platform": "instagram", "followerCount": 210000, "niche": ["beauty", "lifestyle"], "email": "tara@example.com", "feeStructure": "flat_fee" }, { "id": "inf-003", "handle": "@skincarebypriya", "platform": "instagram", "followerCount": 42000, "niche": ["skincare", "sustainability"], "email": "priya@example.com", "feeStructure": "gifted" } ]
{
"name": "finsi/influencer-tracking",
"version": "0.1.0",
"summary": "Influencer campaign attribution, UTM management, and ROI measurement",
"skills": {
"influencer-tracking": {
"path": "SKILL.md"
}
}
}