Engage Customers with a QR Code Virtual Line-Up
Published: 2022-12-30 20:46:01

As a customer, there is nothing worse than waiting in a long line-up to enter a store. This is especially true during the current boxing week! With a QR code enabled virtual lineup, customers can  maintain their position while exploring the neighbouring stores. 

Many stores across North America have started implementing virtual lineups. However, most virtual lineups miss a huge opportunity to engage with their customers. In this article, I will showcase a QR code enabled virtual line-up implementation that allows SMS reminders while capturing customers' contact information.

##Getting Started
Here's what you will need for this workflow:

- A QR Code generation tool
- A landing page with a web form
- A CRM tool or equivalent to save customer data
- Ability to send SMS reminders

You may choose various available packages for the workflow mentioned above. For this implementation, I will be using Openscreen's node [SDK](https://docs.openscreen.com/) which provides all the necessary tools for this workflow, including the ability to send SMS messages.

##Implementation
Here's a high level diagram of the workflow: 
![UML diagram of a qr code workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5r6fuimv3duysnr3kwa.png)
### Generate a Dynamic QR Code
Openscreen's SDK makes it extremely straight forward to generate unique dynamic QR codes. These QR codes will generate a unique scanId upon each scan, which will be to fetch the scan data. Openscreen Dynamic QR codes provide high scanability even at a distance. Combined with a simple process to enter the line-up, stores can attract more customers. 
The intent or the destination of this QR code should be a custom landing page with a web-form for your store. Upon scanning this QR code, there will be some backend processing to determine whether a customer is already in the line-up or not. If you are a new customer, you will be directed to the landing page, otherwise, you will see your current position in the line-up. 
Here's how you can create a dynamic QR code:
 ```javascript
// Initiate the Openscreen node SDK 
const { Openscreen } = require("@openscreen/sdk");
require('dotenv').config();
const os = new Openscreen().config({key: process.env.OS_API_KEY, secret: process.env.OS_API_SECRET});
// Obtain ProjectID from Openscreen Dashboard
const projectId = 'YOUR PROJECT ID';

async function main() { 
  
  // Create an asset for a new listing sign being hosted for 123 Main Street 
  const res = await os.project(projectId).assets().create({
    name: 'Store Lineup',
    description: 'Store Line up For Outlet Mall',
    qrCodes: [{
      intent: 'https://www.my-qrcode-app.com',
      intentType: 'DYNAMIC_REDIRECT'
    }]
  });

  // Returns a scannable QR Code image in png format
  const { qrCodeId } = res.asset.qrCodes[0];
  const qrCode = await os.qrCode(qrCodeId).get({format: 'png'})
  await os.saveQrImageDataToFile(qrCode, 'my-dynamic-qr-code.png');

  // View the new asset that you have created 
  console.log('Asset:', JSON.stringify(res, '',2));
}

main().catch((err) => {
  console.error(err);
});
```

### Create a Web Form
The purpose of this form is to capture only the most essential information from the customer - keep it short and simple. Remember to capture the customer's consent to receive future emails. 

After the form is created, you will need to create a UI to display the current spot in the lineup. Stores can use this opportunity to advertise their best selling items on this landing page. 

### Create Your Virtual Lineup Backend
The backend for your virtual lineup involves three major steps - storing the contact data from the front end, storing and retrieving current position and the ability to send SMS reminders if customers reach position less than 5. Using Openscreen's SDK, you can create a contact based on the customer input, and send SMS messages to that contact. 

Here's how you can create an Openscreen contact and send SMS using a template:
```javascript
// Initiate the Openscreen node SDK and include the project ID that you recieved using the Openscreen dashboard 
const { Openscreen } = require("@openscreen/sdk");
require('dotenv').config();
const os = new Openscreen().config({key: process.env.OS_API_KEY, secret: process.env.OS_API_SECRET});
// Obtain projectId from the Openscreen Dashboard
const projectId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
// Capture scanId from the QR code scan
const scanId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';

async function main(){

  // Create a new contact 
  const contact = await os.project(projectId).contacts().create({
    firstName, 
    lastName,   
    cellPhone,
    consent: {
      url: "https://www.openscreen.com/legal", 
      consentedAt: date.now(),
      consentType: 'SMS',
    }
  });
  // Obtain contactId from the response
  const { contactId }  = contact;
  
  // Create an SMS template
  const smsTemplate = await os.project(projectId).smsTemplates().create({
    smsTemplateName = "Position",
    body: "You are now at position 5, please make your way to the {{asset.name}} now.",
  };

  // Send SMS to contact
  const sendSMS = await os.scan(scanId).sms().send({
    contactId: contactId,
    smsTemplateName: "Position",
  };
}

main().catch((err) => {
  console.error(err);
});
```

## Increase Engagement and Satisfaction
With a simple implementation of a QR code line-up, you are able to  to engage customers, increase customer satisfaction and potentially attract more customers to your store. QR code line-ups also make your store stand-out. With the high scanability of QR codes, you can even attract the physical line-ups of your neighbouring stores! It's truly a win-win situation!

If this implementation is of interest to you, feel free to [contact](https://www.openscreen.com/contact-us) Openscreen for similar customized solutions.

Read More: [Use QR Codes More Efficiently](https://dev.to/birinderlobana/5-best-practices-to-use-qr-more-codes-effectively-m5f), [Scan to Cart QR Codes](https://dev.to/birinderlobana/scan-to-cart-qr-codes-2gdc)