A Developer’s Guide to Adding a JavaScript Barcode Scanner to Web Apps

| Developers

Graphic showing barcode on a package being scanned using a smartphone app with the Scandit Barcode Scanner SDK for the Web

When integrating a JavaScript barcode scanner library into your enterprise web app, you’ll need to consider user experience (UX) principles and performance measures in addition to basic image capture and processing.

The last thing you want is to waste a release cycle implementing features that don’t work under real-world conditions.

This blog explains the key UX and performance principles for successfully adding a barcode scanner to websites and web applications using JavaScript. It also includes a step-by-step tutorial for the Scandit Barcode Scanner SDK for the Web.

Why UX matters for web-based barcode scanning

Integrating a barcode scanner library for JavaScript is like trying to isolate and reproduce a memory leak. There are numerous approaches to take. If you don’t know how to invest your time in the right things, there may be wasted effort and user repercussions down the road.

Users need more than a good camera

Good UX is always a sign of a great web application, and barcode scanning is no different. Getting navigation, interaction, and feedback right helps users do their jobs, and gaps in these areas can lead to frustration, failures, and complaints.

Understanding the following UX workflows helps you build the best JavaScript barcode scanner that works for your users rather than hinders them.

Starting the scanner

Web users have enough on their plates without worrying about complex menu navigation or waiting for a barcode scanner to start. Good UX requires an easy and seamless transition into scanning mode on both mobile and desktop devices.

To ensure a fast and smooth transition into scanning mode, you’ll need to consider these application optimizations:

  1. Locate all resources, including libraries, images, and configuration files, on a server under your control to minimize the impact of downtimes and Internet delays associated with third-party servers.
  2. Compile in WebAssembly (Wasm), which uses a compact binary format (.wasm) that is highly efficient in size and load times, for faster downloads and reduced latency. (If using Scandit, this is handled by the Scandit SDK.)
  3. Ensure optimal image compression that balances processing overhead with scanning quality. (If using Scandit, this is handled by the Scandit SDK.)
  4. Pre-load libraries in the application background to avoid making the user wait for a response when they activate barcode scanning.

In-camera aiming assist

Aiming a device camera is a difficult task in situations where the barcode is located in hard-to-reach placements or mixed in with barcodes the user doesn’t want to scan. UX features that make the scanning process easier helps both user efficiency and satisfaction.

Two examples of features that help the user:

  • A viewfinder to help users know when scanning is active and how to position the camera appropriately.
  • Restricting the scan area to help capture barcodes in cluttered areas and improve performance on low-end devices.

Strong and clear feedback

Your web-based barcode scanner should provide immediate and unambiguous feedback on the success or failure of a scan. A slow response leads to user frustration and unclear results may lead to business risks.

A combination of feedback techniques can be used to help the user, such as:

  • Drawing a brush overlay at the location of the detected barcode to confirm that the intended item was scanned by the app.
  • Playing audio and triggering haptic feedback when the scanner performs a capture successfully.

Supporting different scan modes

Options for scanning single and multiple barcodes help users work more efficiently in environments where the number or configuration of barcodes varies (like a shipping warehouse or retail store):

  • Single scan: The user triggers the scanner for every barcode, providing greater control over the scanning experience.
  • Continuous scan: The user triggers the scanner once and the app scans multiple barcodes without further interaction, accelerating workflows in situations where there’s little risk of unwanted or unintentional scans.

Get your JavaScript barcode scanner library

Fast, accurate and reliable scanning performance.

Try for Free

Performance and other development considerations for your JavaScript barcode scanner SDK

An open-source JavaScript barcode scanner library may not be the best choice for business-critical environments like warehouses, retail stockrooms, and last-mile delivery. While open source may offer basic scanning features and easy access to code, the tradeoff comes when users try to use them in real-world conditions.

Here are some considerations to think about when choosing your JavaScript barcode scanner API for web applications.

1. Performance

Whether deployed on mobile or desktop, you should include the following performance requirements in your decision process:

  • Accuracy: Barcode scanning for inventory management, asset tracking, quality control, and similar operations requires a JavaScript library that the user can rely on to scan barcodes with an extremely high level of accuracy. Even a 95% success rate is unlikely to be good enough – you should be looking for greater than 99% success.
  • Speed: A barcode scanner JavaScript library that helps users capture and process barcodes fast means accelerated business operations.
  • Start-up time: To avoid frustrated users and slower operations, your barcode scanning library should support a “standby mode” that minimizes camera start-up delays between scans.
  • Field-of-view and distance: Scanners must handle barcodes on items of various sizes, shapes, and distances from the camera.
  • Scanning barcodes in degraded conditions: A barcode may be torn, obscured, wrapped in plastic, or in motion – your library should be able to handle all these scenarios.

2. Low-light environments

Lighting conditions in the real world vary widely between dark to brightly lit. Consider your stockrooms, back-of-store areas, or nighttime deliveries. Your chosen barcode scanner should maintain speed and accuracy under these conditions.

3. Large device fleets with diverse models

Enterprises often have a diverse fleet of employee devices – especially in Bring-Your-Own-Device (BYOD) situations. These will have different camera specifications and processor architectures.

Your barcode scanner library must be architected and designed for the utmost efficiency, to support operation on platforms ranging from the latest smartphone to legacy, resource-constrained hardware. We list key performance tests below to gauge how well your library performs.

The Scandit Barcode Scanner SDK for the Web is built on a C/C++ foundation, ensuring that the core barcode scanning features are loaded efficiently in the background and consume minimal system resources.

4. Support for different development frameworks

For developers working across platforms, check that your barcode scanner library supports it. Scandit’s barcode scanning products are also available for Native iOS, Native Android, Cordova, Xamarin (iOS, Android, and Forms), .NET (iOS and Android), React Native, Flutter, Capacitor, and Titanium.

Graphic showing barcode scan on a smartphone by the Scandit Barcode Scanner SDK for the Web

Fast, accurate, and reliable scanning with the Scandit Barcode Scanner SDK for the Web

The Scandit Barcode Scanner SDK for the Web, part of the Scandit Smart Data Capture Platform, allows developers to integrate a high-performance JavaScript barcode scanner library into web applications and e-commerce platforms that include SAP/hybris, Magento, and Demandware.

In just a few lines of code, you get advanced barcode scanning capabilities built on an extensible foundation that supports your own UX features and capabilities.

The next sections explain how to implement a customizable web-based barcode scanning interface in just a few steps with the Scandit Barcode Scanner SDK for the Web.

Testing the Scandit SDK for Web is Easy

Integrate with just a few lines of code or use our samples.

Try for Free

Get started with the Scandit SDK

Follow these steps to add the pre-built SDK features to your app for single barcode scanning. You can also test the Scandit SDK using our code samples on GitHub.

The prerequisites for these steps are:

  • The latest stable version of Node.js and npm (required only if including and building the SDK as part of an app, instead of including it as an external resource from a CDN in HTML).
  • A valid Scandit Data Capture SDK license key. You can sign up for a free test account at ssl.scandit.com.

Although not covered here, the Scandit Barcode Scanner SDK for the Web also supports scanning multiple barcodes at once (batch scanning). The instructions for setting up and using this capability are located in our Batch Scanning And AR documentation.

1. Add the SDK to your project

There are two ways to add the SDK: as an external resource from a CDN in HTML or as a package dependency via npm.

1. To add the SDK as an external resource

You can use the jsDelivr or UNPKG CDN to specify a certain version (range) and include and import from our library as follows (example for barcode capture):

<!-- polyfill browsers not supporting import maps  -->
<script async src="https://ga.jspm.io/npm:es-module-shims@1.7.3/dist/es-module-shims.js"></script>
<script type="importmap">
  {
    "imports": {
      "scandit-web-datacapture-core": "https://cdn.jsdelivr.net/npm/scandit-web-datacapture-core@[version]/build/js/index.js",
      "scandit-web-datacapture-barcode": "https://cdn.jsdelivr.net/npm/scandit-web-datacapture-barcode@[version]/build/js/index.js"
    }
  }
</script>

<script type="module">
  // Import everything
  import * as SDCCore from "scandit-web-datacapture-core";
  import * as SDCBarcode from "scandit-web-datacapture-barcode";

  // And/or import only needed items (examples)
  import { DataCaptureContext, Camera } from "scandit-web-datacapture-core";
  import { BarcodeCapture } from "scandit-web-datacapture-barcode";

  // Insert your code here
</script>

Alternative links for UNPKG are here and here.

Alternatively, you can put the same JavaScript/TypeScript code in a separate file via:

<script type="module" src="script.js"></script>

2. To add the SDK using npm

Run this command from your project’s root folder:

npm install --save scandit-web-datacapture-core scandit-web-datacapture-barcode

Import and use whatever is needed from the library in your JavaScript/TypeScript code by using:

// Import everything
import * as SDCCore from "scandit-web-datacapture-core";
import * as SDCBarcode from "scandit-web-datacapture-barcode";

// And/or import only needed items (examples)
import { DataCaptureContext, Camera } from "scandit-web-datacapture-core";
import { BarcodeCapture } from "scandit-web-datacapture-barcode";

// Insert your code here

3. Additional steps

When using the Scandit Barcode Scanner SDK for the Web, you must set the camera as the frame source for various capture modes. The camera permissions are handled by the browser, and can only be granted if a secure context is used and explicitly accepted by the user when needed.

To configure the scanner to work as a Progressive Web App (PWA), to allow users to work offline, using workbox or a tool that uses workbox under the hood, set these options:

{
  globPatterns: ["**/*.{css,html,ico,png,svg,woff2}", "**/*.{wasm,js}"], // Be sure to add also .wasm
  maximumFileSizeToCacheInBytes: 6 * 1024 * 1024, // Increase size cache up to 6mb
  ignoreURLParametersMatching: [/^v/], // Ignore ?v=x.x.x query string param when using importScripts
}

2. Configure and initialize the library

The library needs to be configured and initialized before it can be used via the configure function.

The ConfigureOptions.libraryLocation configuration option must be provided and set to the location of the Scandit Data Capture library/engine location (external WebAssembly files): scandit-datacapture-sdk*.min.js and scandit-datacapture-sdk*.wasm.

WebAssembly requires these separate files, which are loaded by Scandit’s main library at runtime. They can be found inside the engine folder in the library you added and installed via npm or accessed via a CDN:

Please ensure that the library version of the imported library corresponds to the version of the external Scandit Data Capture library/engine files retrieved via the libraryLocation option, either by ensuring the served files are up-to-date or the path/URL specifies a specific version.

If a common CDN is used here (jsDelivr or UNPKG), the library automatically sets up the correct URLs pointing directly at the files needed for the matching library version. It is highly recommended to handle the serving of these files yourself on your website/server, ensuring optimal compression, correct wasm files MIME type, no request redirections, and correct caching headers usage; thus resulting in faster loading.

We recommend calling configure as soon as possible in your application so that the files are downloaded and initialized before the capture process starts.

import * as SDCCore from "scandit-web-datacapture-core";
import { barcodeCaptureLoader } from "scandit-web-datacapture-barcode";

await SDCCore.configure({
  licenseKey: "SCANDIT_LICENSE_KEY",
  libraryLocation: new URL("library/engine/", document.baseURI).toString(),
  moduleLoaders: [barcodeCaptureLoader()]
});

To provide feedback to the user about the loading status, you can use the default UI provided with the SDK or subscribe to the loading status and update your own custom UI.

1. To use the default UI for loading status

const view = new SDCCore.DataCaptureView();

view.connectToElement(document.getElementById("data-capture-view"));
view.showProgressBar();
view.setProgressBarMessage("Loading ...");

await SDCCore.configure({
  licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --",
  libraryLocation: new URL("library/engine/", document.baseURI).toString(),
  moduleLoaders: [barcodeCaptureLoader()],
});

view.hideProgressBar()

const context = await SDCCore.DataCaptureContext.create();
await view.setContext(context);

2. To use your own custom UI for loading status

Subscribe to the loading status of the library by attaching a listener like this:

SDCCore.loadingStatus.subscribe((info) => {
 // updateUI(info.percentage, info.loadedBytes)
});

await SDCCore.configure({
  licenseKey: "SCANDIT_LICENSE_KEY",
  libraryLocation: "/engine",
  moduleLoaders: [barcodeCaptureLoader()]
});

We suggest serving the library files with the proper headers Content-Length and Content-Encoding if any compression is present. In case of missing information, the library shows an estimated progress

3. Create a new data capture context instance

To add capture capabilities to your application, you must create a new data capture context:

// the license key used in configure() will be used
const context = await SDCCore.DataCaptureContext.create();

4. Configure the barcode scanning behavior

Barcode scanning is orchestrated by the BarcodeCapture data capture mode. This class is the main entry point for scanning barcodes. It is configured through BarcodeCaptureSettings and registers one or more listeners that are informed whenever new codes are recognized.

For this blog, we set up barcode scanning for a small list of symbologies. Change this to the correct symbologies for your use case.

const settings = new SDCBarcode.BarcodeCaptureSettings();
settings.enableSymbologies([
    SDCBarcode.Symbology.Code128,
    SDCBarcode.Symbology.Code39,
    SDCBarcode.Symbology.QR,
    SDCBarcode.Symbology.EAN8,
    SDCBarcode.Symbology.UPCE,
    SDCBarcode.Symbology.EAN13UPCA
  ]);

If you are not disabling barcode capture immediately after scanning the first code and do not want the same code to be scanned more than once, consider setting the BarcodeCaptureSettings.codeDuplicateFilter to around 500 or even -1.

Next, create a BarcodeCapture instance with the settings initialized in the previous step:

const barcodeCapture = await SDCBarcode.BarcodeCapture.forContext(context, settings);

5. Register the barcode capture listener to be informed when a new barcode is scanned

To get informed whenever a new code has been recognized, add a BarcodeCaptureListener through BarcodeCapture.addListener() and implement the listener methods to suit your application’s needs.

Implement the BarcodeCaptureListener interface:

const listener = {
  didScan: (barcodeCapture, session) => {
    const recognizedBarcodes = session.newlyRecognizedBarcodes;
    // Do something with the barcodes
  }
};

Add the listener:

barcodeCapture.addListener(listener);

6. Use the built-in camera

The data capture context supports different frame sources to perform recognition. Most applications use the built-in camera of the device, such as the world-facing camera of a smartphone. This blog assumes you are using the built-in camera.

The built-in camera has recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following code shows how to get the recommended settings and create the camera from it:

const cameraSettings = SDCBarcode.BarcodeCapture.recommendedCameraSettings;

// Depending on the use case further camera settings adjustments can be made here.

const camera = SDCCore.Camera.default;

if (camera) {
  await camera.applySettings(cameraSettings);
}

As the frame source is configurable, the data capture context must be told which frame source to use via a call to DataCaptureContext.setFrameSource():

await context.setFrameSource(camera);

The camera is off by default and must be turned on by calling FrameSource.switchToDesiredState() with a value of FrameSourceState.On:

await camera.switchToDesiredState(Scandit.FrameSourceState.On);

7. Use a Capture View to visualize the scan process

When using the built-in camera as the frame source, it helps the user to display the camera preview on the screen together with UI elements that guide the barcode capture process.

To do this, add a DataCaptureView to your view hierarchy:

const view = await SDCCore.DataCaptureView.forContext(context);
view.connectToElement(htmlElement);

To visualize the results of barcode scanning, add the following overlay:

const overlay = await SDCBarcode.BarcodeCaptureOverlay.withBarcodeCaptureForView(barcodeCapture, view);

8. Disable barcode capture

To disable barcode capture, such as when a barcode is recognized, call BarcodeCapture.setEnabled() with false as the parameter.

Disabling barcode capture stops all frame processing by the SDK. However, the camera continues to stream frames until it is turned off by the user. If a frame was in the middle of processing, it is completely processed and delivers any results/callbacks to the registered listeners.

Testing barcode scanning performance on the web

The best way to test a potential JavaScript barcode scanning API is to run it using real-world scenarios. Whether you’re using the Scandit Barcode Scanner SDK for the Web or another barcode scanning library, here are several performance-testing questions to ask:

  • Is there clear guidance and feedback to foster a smooth workflow rather than confuse users?
  • Can you scan barcodes in different orientations, such as upside down and sideways? Flip the device upside down to see how the scanner performs.
  • Can you scan barcodes with reflections and glare?
  • Can you scan barcodes at a distance? Are you able to zoom in if needed?
  • Do you receive scanning feedback in loud environments and while wearing headphones?

You can also use our barcodes sample sheet for quick evaluation.

Get the Scandit Barcode Scanner SDK for the Web now

Helpful UX and high performance are critical goals when selecting and implementing a JavaScript barcode scanner library. Fewer user frustrations and adaptability to growing business demands are far preferable to low adoption rates, bug reports, and unhappy business leaders.

Interested in how the Scandit Barcode Scanner SDK for the Web can be used to turn web-based applications into intuitive, high-performance scanners with minimal set-up time? Sign up for our free 30-day test SDK now.