@monteluke/jaqr
v1.0.4
Published
Dynamic QR Code system Utility
Maintainers
Readme
JaQR
JaQR is a small JavaScript package for building dynamic QR codes. The package can also tag url with a signature, and let you look up who scanned it and when. It also includes a few handy helper function to create action urls — like opening a text message, saving a contact, or pulling up location etc.
Overview of how JaQR package and JaQR API work together
Create a link (eg. to a landing page) and sign it with some info for analysis (eg. name, a user ID, location etc.). Use JaQR API to turn the url into a QR code. (
Check the end to know more about JaQR API)Someone scans the QR code and lands on your page.
Your page (or your server) reads the signature in the url and matches it against the signature that you created early — which help you to analyse user flow.
Also the package can generate urls that does actions on the visitor's phone such as sending a text, saving a contact, opening the dialer, or opening google map.
Quick Usage
const JaQR = require('@monteluke/jaqr');
// 1. Sign a URL before turning it into a QR code
const signedURL = await JaQR.Sign_URL('https://example.com/scan', { campaign: 'summer-sale' });
// 2. On your server, read who scanned it
app.get('/scan', (req, res) => {
const info = JaQR.getClientMetadata(req);
console.log(info); // who scanned, from where, and when
});Signing URLs and Reading Signatures (Client Side)
Sign_URL(url, metadata)
Takes a URL and an object containing the data (like name or user ID) with which the url needs to be signed, and gives back a new URL with a signature attached. Turn this URL into a QR code (using JaQR API).
const signedURL = await JaQR.Sign_URL('https://example.com/scan', { userId: 42, campaign: 'winter-sale'});
// → 'https://example.com/scan?JaQR=a3424541d61275908fee2830bc2ebdbad4c40bf901690794e85f521eadb631df'A couple of things worth knowing:
If
urlalready has a?something=...in it, the function adds the signature with&instead — it won't break your existing query string.You need to pass a
url, or it'll throw an error.
Create_Signature(data)
Turns any object into a unique signature (technically, a SHA-256 hash).
const hash = await JaQR.Create_Signature({ userId: 42, action: 'scan' });
// → '3f6763dc78dde4c264a1e1f804ea76e2e085a6b54873cd2df9e39b069de87377'Note : The same data in a different key order produces a different signature (e.g. { a: 1, b: 2 } vs { b: 2, a: 1 }). Keep your key order consistent if you ever need to compare one signature against another you made earlier.
Get_Signature()
Function to pull the signature from the URL of the page.
// Page URL: https://example.com/page?JaQR=a3f9b2~~
const sig = JaQR.Get_Signature();
// → 'a3f9b2'Returns null if there's no signature in the URL.
Function to Analyse User Flow (Server Side)
Take the request object and hands back info about the request like visitor's ip address, device etc.
| What you get | What it means |
|---|---|
| signature | The tracking signature from the url, or an empty string if there isn't one |
| ip | The visitor's IP address |
| device | Their browser/device info, or "Unknown" if it's not available |
| timestamp | The date and time of the scan, e.g. 03/16/2026, 10:30 AM |
app.get('/track', (req, res) => {
const meta = JaQR.getClientMetadata(req);
console.log(meta);
// { signature: 'a3f9...', ip: '192.168.1.1', device: 'Mozilla/5.0...', timestamp: '03/16/2026, 10:30 AM' }
});Functions to create action URLs
These four helper functions create action urls. Use it to create QR Code to trigger certain actions.
| Function | Action |
|---|---|
| convertToSMSURL | Opens their Messages app with a phone number and message ready to send |
| getVCardBytes | Downloads a contact card that they can save straight into their phone |
| convertToTelURL | Opens their dialer with a phone number ready to call |
| convertToLocationURL | Opens Google Maps at a given address |
convertToSMSURL({ ph, message, device_OS })
JaQR.convertToSMSURL({ ph: '+155512345673', message: 'Hello!', device_OS: 'ios' });
// → 'sms:+155512345679&body=Hello!'
JaQR.convertToSMSURL({ ph: '+155512345673', message: 'Hello!', device_OS: 'android' });
// → 'sms:+155512345673?body=Hello!'The ph should contain the country code and the 10 digit phone number in E.164 format. device_OS should be "ios" or "android" — iPhones and Android phones expect the message body to be attached slightly differently, so this makes sure the link works on both.
getVCardBytes({ firstname, lastname, organisation, email, ph })
Builds a downloadable contact card (a .vcf file). organisation, email, and ph are optional — include whatever you have. The ph should contain the country code and the 10 digit phone number in E.164 format.
const bytes = JaQR.getVCardBytes({
firstname: 'Jane',
lastname: 'Doe',
organisation: 'Acme Corp',
email: '[email protected]',
ph: '+155598765439'
});
// To let someone download it in the browser:
const blob = new Blob([bytes], { type: 'text/vcard' });
const url = URL.createObjectURL(blob);convertToTelURL({ ph })
JaQR.convertToTelURL({ ph: '+155512345673' });The ph should contain the country code and the 10 digit phone number in E.164 format.
convertToLocationURL({ street, city, state, zipcode, country })
All fields are optional — include as much as possible for accuracy.
JaQR.convertToLocationURL({
street: '1600 Amphitheatre Pkwy',
city: 'Mountain View',
state: 'CA',
zipcode: '94043',
country: 'USA'
});
// → 'https://www.google.com/maps/search/?api=1&query=1600%20Amphitheatre%20Pkwy%2C%20Mountain%20View%2C%20CA%2C%2094043%2C%20USA'Important to know
About the package: JaQR is a plain CommonJS module with no dependencies — just
require('@monteluke/jaqr')and go.Older Node versions:
Sign_URLandCreate_Signaturerely on the Web Crypto API, which is built into every browser and, in Node.js, is available by default from v19 onward (stable in v20+). On an older Node version, add this one line before yourequireJaQR:if (!globalThis.crypto) globalThis.crypto = require('node:crypto').webcrypto;The JaQR API: This package is made to be paired with JaQR API (Which is made by the same Author) that generates highly customizable QR Code.
Contribution & Maintenance
JaQR is a small package maintained by the author. Since this package is made to be used along with JaQR API (which is not free of use), I'm not currently accepting pull requests or any feature requests. You can fork and modify for your own usage.
