Install perfume.js via npm
masterInstall the perfume.js package using npm to add it to your project dependencies.
npm install perfume.js --saverepository·master·Indexed 25 days ago
https://github.com/zizzamia/perfume.jsA lightweight web performance monitoring library (version 9.4.1) for measuring user-centric performance metrics and Web Vitals. It collects field data using modern Performance APIs, providing enriched device data, Navigation Timing, and support for tracking User Journey steps and Element Timing via HTML attributes.
Install the perfume.js package using npm to add it to your project dependencies.
npm install perfume.js --saveUse the Angular CLI to generate new project entities.
ng generate component component-nameng generate <type> <name> where <type> can be directive, pipe, service, class, guard, interface, enum, or module.ng generate component component-nameng e2e command.ng e2eUser Journey steps track 'system time' (time the user is blocked by the system, e.g., navigating or fetching data).
steps object to initPerfume mapping step names to marks (start/end events) and a threshold.markStep(stepName) to trigger the start or end of a defined step.trackUJNavigation() during application navigation changes to remove 'stale' steps (steps that started but never finished due to navigation).// 1. Defining Steps
export const steps = {
load_screen_A: {
threshold: ThresholdTier.quick,
marks: ['navigate_to_screen_A', 'loaded_screen_A'],
},
load_screen_B: {
threshold: ThresholdTier.quick,
marks: ['navigate_to_screen_B', 'loaded_screen_B'],
},
};
initPerfume({ steps });
// 2. Marking the start of a step
markStep('navigate_to_screen_B');
// 3. Handling navigation (e.g., in React)
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
const location = useLocation()
React.useEffect(() => {
trackUJNavigation();
}, [location])
...
}ng test command.ng testng build to compile the project. Build artifacts are placed in the dist/ directory. For a production-ready build, include the --prod flag.ng serve command. The application will be available at http://localhost:4200/.ng serveYou can import the library using standard ESM syntax or via the UMD bundle located in node_modules.
ESM Import:
import { initPerfume } from 'perfume.js';UMD Import:
import { initPerfume } from 'node_modules/perfume.js/dist/perfume.umd.min.js';import { initPerfume } from 'perfume.js';To track when specific HTML elements (images, text nodes) are displayed, add the elementtiming attribute with a unique identifier to the element. Enable this feature by setting elementTiming: true in initPerfume.
<h1 elementtiming="elPageTitle" class="title">Perfume.js</h1>
<img
elementtiming="elHeroLogo"
alt="Perfume.js logo"
src="https://zizzamia.github.io/perfume/assets/perfume-logo-v5-0.0.png"
/>initPerfume({
elementTiming: true,
analyticsTracker: ({ metricName, data }) => {
myAnalyticsTool.track(metricName, data);
}
});
// Perfume.js: elPageTitle 256.00 ms
// Perfume.js: elHeroLogo 1234.00 msThe following options are available in the initPerfume configuration object:
resourceTiming (boolean): Enable resource timing collection.elementTiming (boolean): Enable element timing collection.analyticsTracker (function): Callback function receiving metric data.maxMeasureTime (number): Maximum time to measure.enableNavigtionTracking (boolean): Enable navigation tracking.const options = {
resourceTiming: false,
elementTiming: false,
analyticsTracker: options => {},
maxMeasureTime: 30000,
enableNavigtionTracking: true,
};By setting resourceTiming: true in the initPerfume configuration, Perfume.js collects performance metrics for document-dependent resources (CSS, scripts, images, etc.) and provides a dataConsumption object grouping usage by Kb.
initPerfume({
resourceTiming: true,
analyticsTracker: ({ metricName, data }) => {
myAnalyticsTool.track(metricName, data);
}
});
// Perfume.js: dataConsumption { "css": 185.95, "fetch": 0, "img": 377.93, ... , "script": 8344.95 }You can send Perfume.js metrics to Google Analytics by using the analyticsTracker callback. Note that for cls (Cumulative Layout Shift), the value must be multiplied by 1000 to be sent as an integer.
const metricNames = ['TTFB', 'RT', 'FCP', 'LCP', 'FID', 'CLS', 'TBT'];
initPerfume({
analyticsTracker: ({ attribution, metricName, data, navigatorInformation, rating, navigationType }) => {
if (metricNames.includes(metricName)) {
ga('send', 'event', {
eventCategory: 'Perfume.js',
eventAction: metricName,
// Google Analytics metrics must be integers, so the value is rounded
eventValue: metricName === 'cls' ? data * 1000 : data,
eventLabel: navigatorInformation.isLowEndExperience ? 'lowEndExperience' : 'highEndExperience',
// Use a non-interaction event to avoid affecting bounce rate
nonInteraction: true,
});
}
}
});