AMP Platform Dashboard — Performance Analysis
URL: https://platform.sb.amp.vg/#dashboard/partnersales | Date: March 1, 2026 | Environment: Sandbox
1. Core Web Vitals Summary
| Metric |
Measured Value |
Target |
Rating |
| LCP (Largest Contentful Paint) |
7,222 ms |
< 2,500 ms |
POOR |
| CLS (Cumulative Layout Shift) |
0.23 |
< 0.1 |
POOR |
| TTFB (Time to First Byte) |
2,434 ms |
< 800 ms |
POOR |
LCP Breakdown
The LCP element is the brand logo image (brand-logo-nice.png). The 7.2s LCP breaks down as:
| Phase | Duration | % of LCP | Notes |
| Time to First Byte (TTFB) | 2,434 ms | 33.7% | Server response is very slow |
| Resource Load Delay | 14 ms | 0.2% | Acceptable |
| Resource Load Duration | 649 ms | 9.0% | Image download |
| Element Render Delay | 4,124 ms | 57.1% | JS execution blocks rendering |
CLS Root Cause
The CLS score of 0.23 is caused by:
- Unsized brand logo image — The
<img> for brand-logo-nice.png has no width/height attributes. When it loads, it pushes content down, causing a layout shift of 0.22.
- Non-composited skeleton animations — 4
skeletonAnimation CSS animations that cannot be hardware-accelerated.
2. Request Waterfall Overview
The dashboard loads in a 4-level deep waterfall with a critical path of 7,074 ms. The architecture creates multiple sequential dependencies that prevent parallel loading:
Level 1: Document HTML (304 KB, 2,980 ms)
Level 2: ├── newui.js (parse + execute)
├── Render-blocking CSS ×3 + twilio.js
Level 3: │ ├── /dashboard/partnersales (SPA navigation)
│ ├── GetProfileDetails → GetAssignedPersonaDetails (chained!)
│ ├── GetNavigationTopBanner
│ └── GetTotalUnreadNotificationsForUser
Level 4: │ ├── 11 widget HTML requests (parallel)
│ ├── bridge/ask/ai (885 KB!)
│ ├── Widget template JS loads (per widget)
│ └── Widget API data calls (per widget)
Key bottleneck: The chain Document → newui.js → GetProfileDetails → GetAssignedPersonaDetails → widgets is entirely sequential. Nothing on the dashboard can render until this 4-step chain completes (~5.3 seconds).
3. All Requests — Detailed Breakdown
Phase 1: Document Load (0 – 2,980 ms)
| # | Request | Method | Size | Server Time | Issues |
| 1 |
/ (HTML document) |
GET |
304 KB |
2,434 ms TTFB |
No gzip compression; ~200 KB of inline theme CSS; slow server response |
Phase 2: Static Assets (2,448 ms – 2,982 ms)
| # | Resource | Type | Render-Blocking? | Cache | Issues |
| 2 | default.css | CSS | Yes | Cloudflare, 4hr TTL | Short cache for hashed URL |
| 3 | newui.css | CSS | Yes | Cloudflare, 4hr TTL | Short cache for hashed URL |
| 4 | IBM Plex Sans (Google Fonts) | CSS | Yes | Cached | — |
| 5 | Roboto (Google Fonts) | CSS | Yes | Cached | — |
| 6 | Open Sans (Google Fonts) | CSS | Yes | Cached | — |
| 7 | twilio.js | JS | Yes | Cloudflare, 4hr TTL | Should NOT be render-blocking |
| 8 | jquery.libs.js | JS | No | Cloudflare, 4hr TTL | — |
| 9 | newui.js | JS | No | Cloudflare, 4hr TTL | — |
| 10 | jquery-ui.min.js | JS | No | Google CDN | — |
| 11 | echarts.min.js | JS | No | Cloudflare CDN | — |
| 12 | echartsHelper.js | JS | No | Origin, 24hr TTL | — |
| 13 | brand-logo-nice.png (LCP) | IMG | No | TTL: 0 (none) | No cache; no fetchpriority="high" |
Phase 3: SPA Navigation + Core APIs (3,444 ms – 4,409 ms)
These fire after newui.js parses and executes the SPA hash-router:
| # | API Endpoint | Method | Response Size | Server Time | Issues |
| 14 |
/dashboard/partnersales |
GET |
83 KB |
~3,400 ms wait |
Dashboard skeleton HTML with inline CSS/JS; no gzip |
| 15 |
/api/GetProfileDetails |
POST |
750 B |
~850 ms |
Returns user profile, logo URLs, engagement level |
| 16 |
/api/GetNavigationTopBanner |
POST |
110 B |
~600 ms |
Returns empty string — wasted call |
| 17 |
/api/GetTotalUnreadNotificationsForUser |
POST |
95 B |
~700 ms |
700 ms to return a single integer |
Phase 4: Persona Chain — Critical Path Bottleneck (4,300 ms)
| # | API Endpoint | Method | Response Size | Server Time | Issues |
| 18 |
/api/GetAssignedPersonaDetails |
POST |
250 B |
~850 ms |
Depends on GetProfileDetails; blocks ALL widget loading |
Critical path issue: GetAssignedPersonaDetails cannot start until GetProfileDetails completes. This sequential dependency adds ~1,700 ms to the critical path. Both calls return small JSON and could be merged into a single endpoint or parallelized.
Phase 5: Widget Requests — Parallel Burst (6,788 ms – 6,890 ms)
All fired in parallel after persona details resolve. Each returns server-rendered HTML with inline JS:
| # | Widget Request | Size | Issues |
| 19 | /bridge/ask/ai (BridgeAI chatbot) | 885 KB | Massive response; should be lazy-loaded on interaction |
| 20 | /api/GetAnnocmentNotificationInfo | 190 B | Returns "no announcement" — wasted call |
| 21 | /widgets/userprofile/version/3 | 6 KB | HTML + inline JS, triggers templateJS sub-request |
| 22 | /widgets/organizationprofile/version/2 | ~5 KB | HTML + inline JS, triggers templateJS sub-request |
| 23 | /widgets/yourchannelmanagers/version/3 | ~4 KB | HTML + inline JS, triggers templateJS sub-request |
| 24 | /widgets/webbanner?version=5 | ~3 KB | Banner widget |
| 25 | /widgets/custom/quickactionlink | ~4 KB | Quick action links |
| 26 | /widgets/webbanner?version=4 | ~3 KB | Banner widget |
| 27 | /widgets/partnertiergoal/progress | ~5 KB | Tier goal progress chart |
| 28 | /widgets/registereddealsdonut | 25 KB | Deal donut chart + inline JS |
| 29 | /widgets/dealtoopportunities/version/3 | ~8 KB | Opportunity list table |
| 30 | /widgets/webbanner?version=3 | ~3 KB | Banner widget |
Phase 6: Widget Sub-Requests (7,000 ms+)
After each widget HTML loads, it fires its own template JS fetch and then API data calls (3 round trips per widget):
| # | Request | Type | Issues |
| 31 | widgets/userprofile/templatejs | Template JS | Each widget requires HTML → Template JS → API = 3 sequential round trips |
| 32 | widgets/custom/quickactionlink/templatejs | Template JS |
| 33 | widgets/yourchannelmanagers/templatejs | Template JS |
| 34 | widgets/organizationprofile/templatejs | Template JS |
| 35 | 3× /auto2/{id}/... | Banner content | 3 separate requests for banner content |
| 36 | /api/GetChannelManagersForUser | API (JSON) | Returns FULL user objects (~10 KB+ per user) with photo metadata, all URLs, login history, social profiles — massive over-fetching |
| 37 | /api/GetTierData | API (JSON) | — |
| 38 | /api/GetListedQuickActionModules | API (JSON) | — |
| 39 | /api/GetAllLeadRequests | API (JSON) | — |
| 40 | /api/GetThumbnailForWidget | API (JSON) | — |
| 41 | /api/GetTierGoalDataProgress | API (JSON) | — |
| 42 | /api/GetContactInfoForDealRegistration | API (JSON) | — |
| 43 | /api/GetApprovedDetailsOfDealRequest | API (JSON) | — |
| 44 | 3× /api/getInteractiveBannerTemplate | API (JSON) | Sequential banner template calls |
| 45 | 3× /api/getInteractiveBannerPage | API (JSON) | Sequential banner page calls |
| 46 | /api/GetDealRegistrationDataCountStatus | API (JSON) | — |
Third-Party Scripts
| Script | Transfer Size | Main Thread Time | Notes |
| Intercom | 1.1 MB | 199 ms | Chat widget; consider lazy loading |
| Cloudflare CDN | 1.3 MB | 39 ms | Static asset delivery |
| WalkMe | ~50 KB | Multiple XHR calls | User guidance; fires 4+ API calls |
| Google CDN (jQuery UI) | 320 KB | 28 ms | — |
| Google Fonts | 248 KB | — | 3 font families |
Other Frontend Issues
| Issue | Impact | Details |
| Forced Reflows (Layout Thrashing) | 222 ms wasted | jQuery We() function triggers 169 ms of forced synchronous layout. Tooltip positioning (applyPlacement) adds 11 ms more. |
| DOM Size | 1,098 elements, depth 17 | <body> has 61 direct children. Style recalculations up to 55 ms affecting 432 elements. |
| No preconnect hints | +200-400 ms | No <link rel="preconnect"> for cache.sb.amp.vg, fonts.googleapis.com, or fonts.gstatic.com. |
4. Total Request Count Summary
| Category | Count | Total Transfer |
| Document / page HTML | 2 | ~387 KB |
| Widget HTML responses | 11 | ~95 KB |
| BridgeAI chatbot | 1 | 885 KB |
| API calls (JSON) | ~25 | ~50 KB |
| Widget template JS | 5 | ~15 KB |
| Static bundles (CSS/JS) | ~12 | ~1.5 MB (cached on repeat) |
| Fonts | ~8 | ~400 KB |
| Images | ~6 | ~280 KB |
| Third-party (Intercom, WalkMe) | ~10 | ~1.5 MB |
| TOTAL | ~80 requests | ~5.1 MB |
5. Recommended Fixes (Priority Order)
| Priority | Fix | Estimated Savings | Effort |
| P0 |
Enable gzip/brotli compression on all IIS responses (HTML, JSON, JS, CSS). Currently NONE of the origin server responses are compressed. |
~2,300 ms LCP savings |
Low — IIS config change |
| P0 |
Merge GetProfileDetails + GetAssignedPersonaDetails into a single API call to eliminate the sequential dependency on the critical path. |
~850 ms critical path savings |
Medium — Backend change |
| P0 |
Lazy-load BridgeAI chatbot (/bridge/ask/ai) — defer the 885 KB response until user clicks the chat icon instead of loading on every page view. |
885 KB transfer savings + reduced server load |
Medium — Frontend change |
| P1 |
Add width/height to the brand logo image to fix CLS. Add fetchpriority="high" to improve LCP discovery. |
CLS 0.23 → ~0 |
Low — HTML attribute |
| P1 |
Defer twilio.js — add async or defer attribute. It’s render-blocking but not needed for first paint. |
~300 ms FCP improvement |
Low — HTML attribute |
| P1 |
Increase cache TTL for hashed bundles on Cloudflare from 4 hours to max-age=31536000, immutable. URLs already contain content hashes. |
Eliminates re-downloads on repeat visits |
Low — Cache rule change |
| P1 |
Add cache headers to images served from /img/ (currently TTL: 0). At minimum max-age=86400. |
~270 KB saved on repeat visits |
Low — IIS/config change |
| P1 |
Add <link rel="preconnect"> for cache.sb.amp.vg, fonts.googleapis.com, and fonts.gstatic.com. |
~200-400 ms connection setup savings |
Low — HTML tags |
| P2 |
Reduce GetChannelManagersForUser response — currently returns full user objects with every field. The widget only needs name + photo URL. |
~10 KB+ per request; faster server response |
Medium — Backend change |
| P2 |
Eliminate unnecessary API calls: GetNavigationTopBanner (returns empty), GetAnnocmentNotificationInfo (returns "no announcement"). Cache or skip when data is empty. |
2 fewer API calls per page load |
Low — Conditional logic |
| P2 |
Lazy-load Intercom — defer the 1.1 MB Intercom widget until after the page is interactive. |
199 ms main thread + 1.1 MB transfer |
Low — Script loading change |
| P2 |
Extract inline theme CSS from the 304 KB HTML document into a cacheable static file. The ~200 KB of dynamic theme rules are currently inlined on every page load. |
~200 KB per page load |
Medium — Architecture change |
| P3 |
Bundle widget HTML + template JS into a single response per widget to eliminate the 2nd round trip. |
1 fewer round trip per widget × 11 widgets |
High — Widget architecture change |
| P3 |
Optimize user profile image (thumb_400-Ellipse_1.png) — served at 400×400 but displayed at 40×40. Use responsive images or serve the correct size. Convert to WebP. |
~104 KB savings |
Low — Image pipeline |
| P3 |
Investigate server-side TTFB — 2,434 ms for the initial HTML response suggests slow backend rendering. Profile the server-side code for the dashboard page. |
Potentially 1,000+ ms |
High — Backend investigation |
6. Estimated Impact of Top Fixes
If we implement P0 + P1 fixes:
- LCP: 7,222 ms → estimated ~3,500–4,000 ms (50% improvement)
- CLS: 0.23 → estimated ~0.01 (good rating)
- Repeat visit performance significantly improved via caching
If we also implement P2 fixes:
- LCP: estimated ~2,500–3,000 ms (near target)
- Total transfer: ~5.1 MB → estimated ~3 MB
- Total requests: ~80 → estimated ~65
Generated using Chrome DevTools Performance Trace — Lab data, no CPU/network throttling applied.