# Change Your Password Source: https://help.qrtub.com/account/change-password Changing your QRtub password from the Profile screen: the four rules actually enforced, the live checklist, the five-per-15-minutes limit, and what to do if you never set a password Change your password from the Profile screen. Open the user menu at the top right of the dashboard, choose **Profile**, scroll to **Change Password**, enter the new password twice and click **Update Password**. You are not asked for your current password — being signed in is the proof. On success the form shows *Password updated successfully.* and clears both boxes. It does not sign you out or send you anywhere, so you can carry on working. ## The password rules Four requirements, all enforced before the request is sent and again by the authentication service: * At least **8 characters** * At least one **upper case** and one **lower case** letter * At least one **number** * At least one **special character** from `!@#$%^&*()_+-=[]{};':"\|,.<>/?` There is no maximum length and no restriction on what else the password contains. A space is allowed inside a password but does not count as the special character. A checklist under the New Password box ticks each rule off as you meet it, plus a *Passwords match.* row once you have filled in the confirmation. That checklist updates about half a second after you stop typing, so it can lag behind fast typing or a password manager filling the field — the check performed when you click **Update Password** is the one that decides. If a rule is unmet, the form names the first one it hits, for example *Password must contain at least one special character.* Anything the authentication service itself rejects is shown to you verbatim in a red box above the form — that is where you would see it if the new password is the same as the one you already have. ## If you never set a password If someone invited you to a team and you had no QRtub login yet, your invitation email contains a one-time link that signs you in and lands on a **Set a password** screen. It enforces the same four rules, and setting a password there takes you straight to the dashboard. That screen also offers **Skip for now**. Taking it leaves you signed in with no password set, so on your next visit the password box on the login screen will not work for you — set a password from the Profile screen while you are still signed in, or use the recovery email flow below. The Set a password screen and the Profile form submit to exactly the same place, so either route gets you to the same result. ## If you cannot sign in Use **Forgot password** on the login screen and enter your email address. QRtub sends a recovery email; opening its link brings up **Reset your password**, which applies the same four rules. After saving, you are returned to the login screen a few seconds later to sign in with the new password. Two failure messages are worth recognizing. *This reset link is invalid or has expired. Please request a new one.* means the recovery link is no longer usable — request another from Forgot password. An unauthorized error on the Profile form means your session has ended; sign in again and retry. ## The rate limit Password updates are limited to **five per 15 minutes per account**, counted across both the Profile form and the reset screen. Past that you get *Too many requests. Please try again later.* along with how long to wait. Nothing is locked and nothing needs to be reset — the next attempt after the window succeeds. ## Related * [Account Overview](/account/overview) — everything else the Profile screen shows, and what it will not let you change * [Accepting a Team Invitation](/team/accept-invitation) — the invitation link that leads to the Set a password screen * [Team Overview](/team/overview) — how your login relates to the team that owns your Collections # Account Overview Source: https://help.qrtub.com/account/overview What your Profile screen shows about your personal QRtub login — email, user ID, sign-up date, verification state, sign-in method and your teams — and which of those you can change Your account is your personal login to QRtub: one email address, one password. Teams, Collections, Items and Links all belong to a team, not to you — your account is what gets you in and what a team adds when it invites you. The Profile screen is where you see that account. It is almost entirely read-only: the only thing on it you can change is your password. It also does not depend on which team is currently active, so switching teams does not change anything shown here. ## Where to find it Open the user menu at the top right of the dashboard — the circle showing your initials — and choose **Profile**. That same menu holds the light/dark/system theme picker and **Sign out**. Nothing else about your login lives anywhere else in the app. ## What the Profile screen shows **Account Information** lists four values: * **Email Address** — the address you sign in with. * **User ID** — your internal identifier, shown as the first 16 characters followed by an ellipsis. The full value is not displayed and cannot be copied from this screen. * **Account Created** — the date the account was created. * **Email Verified** — **Verified** or **Pending**. An account created through the sign-up form becomes verified when the confirmation email's link is opened; an account created by paying at checkout is marked verified the moment it is created. This indicator is informational — no QRtub feature is switched on or off by it. **Quick Stats** shows three tiles. **Teams** counts your active team memberships. **Auth Provider** records how the account signs in; QRtub only offers email sign-in — a password, or a one-time emailed link — so this reads *Email*. **Account Status** is a fixed label that always reads *Active*: it is not a computed state and says nothing about subscriptions or payment. ## The two team lists, and why they differ **Your Teams** lists every team where you are an active member, whatever your role, with each team's name and URL slug. **Your teams & subscriptions** lists only the teams you *own*, each with its current plan and a **Manage** or **Subscribe** button that switches your active team and opens that team's settings. A team you were invited to therefore appears in the first list and not the second — that is expected, not a fault. If you own no teams, this section offers a link to choose a plan instead. ## What you cannot change here * **Your display name.** The heading above your email is your name if one is stored, otherwise the part of your email address before the `@`. Nothing in QRtub writes a name, so in practice it is always the email prefix, and there is no field to edit it. * **Your photo.** If a photo is stored on the account it is shown; there is no upload control, so most accounts show an initials circle. * **Your email address.** There is no way to change the address on an existing account from inside the app. * **Deleting your account.** There is no self-serve account deletion. Removing yourself from a team is a separate action on the team page and leaves your login intact. For anything in that list, email [hi@qrtub.com](mailto:hi@qrtub.com). ## Related * [Change Your Password](/account/change-password) — the exact rules, and what to do if you never had a password * [Team Overview](/team/overview) — the shared workspace that actually owns your Collections and Links * [Billing Is Per-Team](/billing/per-team-billing) — why a subscription attaches to a team rather than to you # Managing Your Subscription Source: https://help.qrtub.com/billing/customer-portal The Manage subscription button hands off to Stripe's billing portal for one team — where the payment method, invoices, and cancellation live, and what QRtub itself does not track Everything about an existing subscription — the card on file, past invoices, canceling — happens in Stripe's billing portal, not in QRtub. Open it from the team page: **Subscription → Manage subscription**. QRtub creates a one-off session for that team's subscription and sends you to Stripe's own site, and Stripe returns you to the team page when you are done. ## It is scoped to one team, and only the owner can open it The button only exists for the team owner, and the session it creates is for the subscription belonging to the team whose page you opened it from. If you own several paid teams, open the portal from the team you actually mean — or go to **Profile → Your teams & subscriptions** and press **Manage** next to the team you want, which switches you to that team before landing you on its page. Asking for the portal on a team that has never been subscribed, or one you do not own, returns an error rather than an empty portal. ## What you can do there * **Update the payment method** — a new card, or a replacement after one expires. * **Download invoices and receipts** — the billing history for that team, which is where to go for anything your accountant needs. * **Cancel the subscription.** * **Change tier or billing interval**, if the portal is set up to offer it. If you do not see the option, email [hi@qrtub.com](mailto:hi@qrtub.com) instead of buying a second subscription for the same team. Card details are entered on Stripe's pages throughout. QRtub does not receive or store them. ## What QRtub does not track QRtub records which plan a team is on and the status of its subscription, and nothing else about the billing cycle. It does not store your renewal date, your invoice history, or the fact that a cancellation is scheduled. The portal is the only place those exist. The consequence worth knowing: **if you cancel at the end of the billing period, the team page keeps showing the plan as normal until the subscription actually ends.** There is no "cancels on the 14th" notice in QRtub, and no countdown. Only when the subscription genuinely lapses does the team page change to show the plan name followed by `(cancelled)`. If you have canceled and want to check the effective date, look in the portal or in Stripe's confirmation email. ## The button stays after you cancel A canceled team keeps its **Manage subscription** button rather than reverting to a plan picker, which is deliberate — it is how you get back in for old invoices after the subscription has ended. The card shows the plan name with `(cancelled)` next to it so you can tell the two states apart at a glance. If you want that team on a plan again and the portal does not offer a way back, email [hi@qrtub.com](mailto:hi@qrtub.com) rather than guessing. ## Related * [Subscription Status](/billing/subscription-status) — what each status means and where it shows * [Upgrading a Team's Plan](/billing/upgrade-a-team) — putting a plan on a team that has none * [Billing Is Per-Team](/billing/per-team-billing) — why each team has its own portal session * [Plans Overview](/billing/plans-overview) — tiers, intervals, and GST # Billing Is Per-Team Source: https://help.qrtub.com/billing/per-team-billing A subscription attaches to one team rather than to your login, so one person can own several teams that each carry their own plan, payment method, and invoices In QRtub, a plan belongs to a **team**, not to your login. If you own three teams, that is three separate subscriptions — three plans, three payment methods, three sets of invoices. There is no account-wide plan sitting above them. ## Why it works this way A team is the thing that holds the work: the Collections, the Items, the Links, and the people who manage them. Attaching payment to the team means the unit that owns the work is the unit that gets paid for, and it keeps separate operations genuinely separate. That matters most when one person is running more than one operation. A contractor managing their own plant fleet in one team and a client's site in another can put each on the plan that fits it, hand over or wind down one without touching the other, and give each its own invoice trail for their own accounting. ## One person, several teams You can create additional teams from the team switcher at any time. A team created that way starts with no subscription attached — it is a working team immediately, and subscribing it is a separate step you take when you want to. To see everything at once, open **Profile → Your teams & subscriptions**. That section lists every team you own, with each team's current plan next to it and a button that takes you to that team's page — **Manage** for a team that already has a subscription, **Subscribe** for one that does not. It only lists teams you own, so teams where you are a member rather than the owner do not appear. ## Only the team owner sees the billing controls The **Subscription** card on the team page is rendered for the team owner only. Other members of the same team do not see the card, cannot open the billing portal for it, and cannot start a subscription for it — the checkout and portal requests both check team ownership on the server, not just in the browser. So if you are a member of someone else's team and want to change its plan, the person who owns that team has to do it. If you own the team but signed in with a different account than the one that set it up, you will not see the card either — sign in as the owner. ## A team with no subscription On a team that has never been subscribed, the Subscription card reads **No active subscription** and offers a **Choose a plan** button, and an **Upgrade** button appears in the top bar. That is the state a newly created team starts in. What a plan includes, and how QRtub treats a team whose usage has grown past what its plan advertises, is covered separately in [Plan Limits & Quotas](/billing/plan-limits) — read that page rather than assuming, because the answer is more specific than most software. ## Related * [Plans Overview](/billing/plans-overview) — the tiers, the billing intervals, and how prices are shown * [Upgrading a Team's Plan](/billing/upgrade-a-team) — subscribing a specific team from inside the app * [Managing Your Subscription](/billing/customer-portal) — payment method, invoices, and cancellation * [Plan Limits & Quotas](/billing/plan-limits) — what an allowance is, and what it is not # Plan Limits & Quotas Source: https://help.qrtub.com/billing/plan-limits What each plan includes — how many Links, editors and numbered sequence patterns — and what each of those three allowances actually counts Every plan includes an allowance across three things: how many Links you can hold, how many editors can sign in to manage them, and how many numbered sequence patterns you can claim. All three increase as you move up the tiers. | | Starter | Professional | Scale | | ------------------------------ | ------- | ------------ | ----------------- | | **Links** | 100 | 1,000 | 10,000 | | **Editors** | 1 | 5 | 20 | | **Numbered sequence patterns** | — | 1 | 5 | | **Scanning** | Public | Public | Public or private | [qrtub.com/pricing](https://qrtub.com/pricing) is the current source for these figures and for prices. Enterprise is arranged directly and is not fixed to the numbers above. ## What counts as a Link Every Link you hold, whether or not it is connected to anything yet. That matters more than it sounds, because of how QRtub is normally used. A Link is a permanent address, and printing codes before you know what they will point to is a deliberate workflow — so a batch of 500 codes sitting in a box, connected to nothing, is 500 Links against your allowance. Spare codes count too. The allowance is a count of addresses you have brought into existence, not a count of the ones currently in use. It is also a total, not a monthly rate. You can create your whole allowance on your first day — which is the point, since a print run is an afternoon's work rather than something you meter out over a year. ## What counts as an editor People who sign in to manage the rollout: creating Links, updating destinations, editing Pages, connecting codes to Items. **People who scan your codes are not editors and never need an account.** Public scanning is unlimited and free on every tier. You are paying for the people running the system, not the people using it — a council with five staff and forty thousand residents scanning bin codes needs five editors. The Owner and Editor role labels inside a team are a different question — those are about what a member is allowed to do, not about what your plan includes. See [Team Roles](/team/roles). ## What counts as a numbered sequence pattern A claimed range of sequential Links — `CRA0001TL` through `CRA0999TL`, for example. This is the number people misread, because a pattern is a reserved *range* rather than a single code. One pattern can cover hundreds of Links, which is why the allowance is a much smaller figure than the other two. Numbered patterns start at Professional; Starter does not include them. The Links minted inside a pattern still count against your Link allowance in the normal way. Claiming the range itself does not consume Links — only the codes you actually mint from it do. See [Numbered Links](/links/numbered-links). ## What is the same on every plan Scanning is never limited or charged. Neither is changing where an existing Link points — updating a destination without reprinting is included on every tier, including Starter, because it is the thing QRtub exists to do. ## Related * [Plans Overview](/billing/plans-overview) — the tiers, billing intervals, and how prices are quoted * [Upgrading a Team's Plan](/billing/upgrade-a-team) — moving a team to a larger tier * [Billing Is Per-Team](/billing/per-team-billing) — an allowance belongs to one team, not to your login * [Numbered Links](/links/numbered-links) — what claiming a pattern actually reserves # Plans Overview Source: https://help.qrtub.com/billing/plans-overview The shape of QRtub pricing: three self-serve tiers you can buy at checkout, an Enterprise tier arranged directly, monthly or annual billing, and prices quoted in Australian dollars QRtub has three plans you can buy yourself — **Starter**, **Professional**, and **Scale** — and a fourth, **Enterprise**, that is arranged directly with us rather than through checkout. Each one is bought per team, so the plan you pick applies to that team only. The current figures live on [qrtub.com/pricing](https://qrtub.com/pricing); this page is about the structure around them. ## The three self-serve tiers The tiers stack. Professional includes everything in Starter, and Scale includes everything in Professional, so moving up a tier only ever adds — it never trades one capability for another. * **Starter** — a first rollout. Random and custom Links, printing before the destination exists, updating destinations without reprinting, the Page Editor, data export, and email support. * **Professional** — small teams running several sites or clients. Adds team management, numbered sequence patterns, a larger allowance, and priority support with an onboarding call. * **Scale** — larger operations with a lot of things in the field. Adds more numbered sequence patterns, the largest allowance, and the choice of private or public scanning. The allowances themselves — how many Links, how many editors, how many numbered sequence patterns — are the main thing that changes between tiers. They are described in [Plan Limits & Quotas](/billing/plan-limits), and the numbers are on the pricing page. ## Enterprise is not a checkout button Enterprise has no price in the app and no self-serve path. It exists for unusual shapes — OEMs, developers embedding QRtub, Suppliers, and rollouts whose requirements do not fit a tier — and it is priced per arrangement. The pricing page lists what can be negotiated and the **Contact us** link starts that conversation. The **Need more than Scale?** panel in the in-app plan picker goes to the same place. ## Monthly or annual Every self-serve tier can be billed monthly or annually, and you choose which at checkout. Annual is billed once for the year and is priced at ten months rather than twelve, so the app describes it as two months free. Annual is the option preselected in the in-app plan picker. Switching between monthly and annual later is a change to the subscription itself, which happens through the billing portal — see [Managing Your Subscription](/billing/customer-portal). ## Prices are in Australian dollars, and GST depends on where you are All prices are quoted in AUD. GST is calculated at checkout from the billing address you enter: Australian customers are charged GST on top, and customers outside Australia are not charged GST at all. If you are overseas you are still billed in AUD, and your bank converts at its own rate — any foreign currency fee is between you and your bank. The pricing page has a **Business / Personal** toggle that changes nothing about what you get. Business shows prices excluding GST, because Australian businesses generally claim it back; Personal shows prices including GST, which is the amount actually leaving your account. Same plan, same features, two ways of displaying the same number. ## There is no free trial QRtub does not offer a trial period at this stage — a plan starts when you pay for it. Starter is deliberately priced as the low-commitment way in. ## Related * [Billing Is Per-Team](/billing/per-team-billing) — why the plan attaches to a team rather than your login * [Subscribing to a Plan](/billing/subscribe) — buying a plan and getting your account created * [Plan Limits & Quotas](/billing/plan-limits) — what the per-tier allowances cover * [Managing Your Subscription](/billing/customer-portal) — changing or canceling an existing subscription # Subscribing to a Plan Source: https://help.qrtub.com/billing/subscribe The public checkout path for a brand-new customer: pick a plan and interval, pay with a card at Stripe, and get an account, a first team, and a subscription created together If you do not have a QRtub account yet, you get one by buying a plan. Start at [qrtub.com/pricing](https://qrtub.com/pricing), pick a tier, and QRtub creates your login, your first team, and the subscription together once the payment goes through. There is no separate sign-up step to do first. ## What the flow looks like 1. **Choose a plan on the pricing page** and pick monthly or annual. That takes you to a checkout page inside QRtub. 2. **Confirm or change your choice.** The checkout page shows the plan you picked with its feature list, lets you switch tier or interval, and lists the other plans underneath if you change your mind. 3. **Enter your email address.** This becomes the login for the account that gets created, so use one you can receive mail at. 4. **Pay.** The button sends you to Stripe's own hosted payment page — QRtub never sees or stores your card details. At Stripe's page you enter card details and a billing address. GST is added automatically for Australian billing addresses and not added for addresses outside Australia. If you have a promotion code, there is a field for it there rather than in QRtub. **Card payments only.** Self-serve checkout takes cards. There is no invoice, bank transfer, or purchase-order path through self-serve checkout — if your business needs one, email [hi@qrtub.com](mailto:hi@qrtub.com) rather than working around it. ## What happens after you pay Stripe confirms the payment to QRtub, and QRtub then creates the account, a first team owned by you, and the subscription attached to that team. The team is named from the first part of your email address — you can rename it afterwards in team settings. You will get an email with a magic link. Clicking it signs you in for the first time and takes you to a form to set a password. If it has not arrived after a couple of minutes, check your spam folder before contacting us — the account exists either way, and a password reset from the sign-in page will also get you in. If you close Stripe's page or back out before paying, you land on a cancellation page and nothing is charged. ## If you already have an account, do not use this path Public checkout always sets out to create a new team. If you are an existing customer and want to put a plan on a team you already own, use the in-app upgrade instead — [Upgrading a Team's Plan](/billing/upgrade-a-team) covers it. Going through public checkout again with the same email address gives you a second team with its own subscription, which is a fine thing to want on purpose and an annoying thing to discover by accident. ## One case to know about: a pending invitation on the same email If someone has already invited that email address to their team and the invitation has not expired, QRtub treats the incoming payment differently: it adds you to the team that invited you and does **not** create a new team or record a subscription for that payment. Stripe will still have charged you. That is not a state you can fix from inside the app. If it happens, email [hi@qrtub.com](mailto:hi@qrtub.com) with the address you paid with and we will sort it out. If you know an invitation is waiting for you, accept the invitation first and let the team owner handle the plan for that team. ## Related * [Plans Overview](/billing/plans-overview) — the tiers, intervals, AUD pricing, and GST * [Upgrading a Team's Plan](/billing/upgrade-a-team) — the right path when you are already signed in * [Billing Is Per-Team](/billing/per-team-billing) — why checkout creates a team, not just a login * [Subscription Status](/billing/subscription-status) — what QRtub shows once the subscription is live # Subscription Status Source: https://help.qrtub.com/billing/subscription-status The status values QRtub records from Stripe for a team's subscription, what each one factually means, and exactly how each appears on the team page and in your profile Every team with a subscription carries a status that QRtub receives from Stripe and stores against that team. It is the answer to "is this team's payment in good order right now", and it is the only billing state QRtub keeps besides the plan name. ## What each status means | Status | What it means | What you see in QRtub | | ---------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | `active` | Paid and current. | The plan name on the team page; a green badge in your profile. | | `trialing` | Inside a trial period. QRtub does not sell trials, so you would not normally see this. | The plan name; a green badge. | | `past_due` | An invoice failed and Stripe is retrying it. | The plan name, with no warning of any kind. | | `canceled` | The subscription has ended. | The plan name followed by `(cancelled)`; an amber badge. | Stripe can also report `incomplete`, `unpaid`, or `paused`. QRtub stores those values as it receives them but has no specific display for them: the team page still shows the plan name, the profile badge turns gray rather than green, and the **Upgrade** prompt reappears in the top bar. If you see that combination, the subscription is not in good standing and the billing portal will tell you why. ## Where it shows Two places, both for the team owner only: * **The team page**, under **Subscription** — the plan name, or `No active subscription` if the team has never been subscribed. * **Profile → Your teams & subscriptions** — one row per team you own with a colored badge: green for a subscription in good order, amber for one that has been canceled, gray for a team with no subscription. ## A failed payment is quiet inside QRtub This is the one to plan around. When a payment fails, Stripe emails you and starts retrying, and QRtub records the team as `past_due` — but the team page still shows the plan name with no banner, no color change, and no notification. Nothing in the app tells you a card has bounced. So a failed payment reaches you through Stripe's email, not through QRtub. Make sure the address on the subscription is one somebody actually reads, and if you suspect a card has expired, open the billing portal and check rather than looking for a warning in the app. [Managing Your Subscription](/billing/customer-portal) covers how to get there. ## Status changes arrive when Stripe reports them QRtub does not poll Stripe. It updates a team's status when Stripe notifies it of a change — normally within a few seconds of the event. That means a payment you have just made, or a change you have just made in the billing portal, can take a moment to appear on the team page. Reload the page rather than repeating the action. ## The one thing status changes in the app Status decides whether the **Upgrade** button appears in the top bar. It is hidden while a team's subscription is `active`, `trialing`, or `past_due`, and shown otherwise — including for a team that has never been subscribed. That prompt is the visible effect of status; what a plan covers is described in [Plan Limits & Quotas](/billing/plan-limits). ## Related * [Managing Your Subscription](/billing/customer-portal) — fixing a payment method, invoices, canceling * [Plan Limits & Quotas](/billing/plan-limits) — what your plan includes * [Billing Is Per-Team](/billing/per-team-billing) — why each team has its own status * [Upgrading a Team's Plan](/billing/upgrade-a-team) — putting a plan on a team that has none # Upgrading a Team's Plan Source: https://help.qrtub.com/billing/upgrade-a-team How a signed-in owner puts a plan on one specific team from inside the app, why only the owner can complete it, and why a team that already has a subscription shows a different button When you are already signed in, you subscribe a team from inside the app rather than through public checkout. Two places open the same plan picker: the **Upgrade** button in the top bar, which applies to whichever team you are currently in, and the **Choose a plan** button on the Subscription card on that team's page. Both attach the new subscription to that one team. ## Picking a plan The picker shows the three self-serve tiers side by side with a monthly / annual toggle, opens with annual selected and Professional highlighted, and has a **Need more than Scale?** panel at the bottom that leads to a contact form for Enterprise. Choosing a tier sends you to Stripe's hosted payment page with the team recorded against the transaction. After payment, QRtub attaches the subscription to that existing team — it does not create another one, which is the difference between this path and [public checkout](/billing/subscribe). You land on a confirmation page afterwards. Activation is automatic, but Stripe's confirmation reaching QRtub takes a few seconds, so if the team page still shows the old state immediately after paying, reload it. ## Only the owner can finish it The **Upgrade** button in the top bar appears for anyone on a team without an active subscription, including members who do not own it. Choosing a plan, though, is checked against team ownership on the server: if you are not the owner, the attempt stops with an error saying only the team owner can do that, and nothing is charged. If that happens to you, you are on someone else's team. Ask whoever owns it to subscribe it — the Subscription card and the billing portal are both owner-only, so there is nothing you can do from your own account. Owners can confirm which teams are theirs under **Profile → Your teams & subscriptions**. ## A team that already has a subscription shows a different button The plan picker only appears for a team with no subscription attached. Once a team has one, the Subscription card shows the plan name and a **Manage subscription** button instead, which hands off to the Stripe billing portal — see [Managing Your Subscription](/billing/customer-portal). That means a genuine tier change on a paid team is a portal action, not an in-app one. QRtub records the new tier when Stripe reports the change, so the team page will show the new plan name shortly after the change goes through. What the portal actually offers depends on how it is configured, so if you cannot find an option to change tier there, email [hi@qrtub.com](mailto:hi@qrtub.com) rather than starting a second subscription for the same team. ## Upgrading several teams Each team is a separate transaction. If you own three teams and want all three on a plan, you subscribe each one — switch to the team, open the picker, pay. There is no bulk or account-wide purchase, because there is no account-wide plan; [Billing Is Per-Team](/billing/per-team-billing) explains why. ## Related * [Billing Is Per-Team](/billing/per-team-billing) — why a subscription belongs to one team * [Managing Your Subscription](/billing/customer-portal) — the portal, and what changes there * [Plans Overview](/billing/plans-overview) — what separates the tiers * [Subscription Status](/billing/subscription-status) — reading the state on the team page # Bulk Assigning, Unassigning, and Deleting Links Source: https://help.qrtub.com/bulk-links/assign-unassign-delete Acting on many Links at once: ticked rows versus 'select all' across every page of results, and the all-or-nothing rule that protects printed codes from a bulk delete Select Links in the list and a bulk menu appears with four actions: **Download QR Codes**, **Assign to Item**, **Unassign from Items** and **Delete Selected**. Anything else — changing a destination, editing fallbacks, renaming — is a per-Link edit. ## Two ways to select, and the difference matters **Ticking rows** operates on exactly the Links you ticked. Straightforward, and limited to what is on screen. **Select all** is different: it selects every Link matching your current view, not just the page in front of you. QRtub sends the *filters* rather than a list of IDs, and resolves them on the server, so "delete all 4,000 unassigned random Links" is one request instead of shipping 4,000 IDs out to your browser and back. The count in the confirmation dialog is the full total, so read it before confirming — that is your check that the scope is what you meant. The scope carries the filters you can see in the list: link type, assigned or unassigned, whether the Link was adopted from a scanned code, any column filters, and your search term. Change the filters, and you change what "select all" means. **One filter cannot be part of a "select all" scope: print batch.** If the list is filtered by batch and you use select all, the operation is refused with a message saying the batch filter is not supported for bulk operations. Tick the rows you want individually instead, filter by something else, or work from the batch's own screen. ## Assigning many Links to an Item **Assign to Item** opens a picker covering every Item in the team, across all Collections, and points every selected Link at the one Item you choose. That is the right shape more often than it sounds — a machine that carries a plate on the cab, a sticker in the engine bay and a spare tag in the office is one Item with three Links. But it does mean bulk assign cannot pair a list of Links with a list of Items one-to-one; that is a per-Link action, or a job for the Collection's link generation setting. A Link points at no more than one Item, so assigning replaces any existing assignment without asking. ## Unassigning many Links **Unassign from Items** detaches every selected Link and returns it to the unassigned pool. The Links stay alive and the printed codes keep resolving — a scan lands on the neutral "not connected yet" page instead of the Item's Page. There is no print-status restriction on this. Detaching a code that is already installed is a normal, expected thing to do when the equipment behind it changes. ## Deleting many Links **Delete Selected** is permanent and there is no undo — the slugs stop resolving and anyone scanning those codes gets "page not found". QRtub asks for confirmation with the count first. The important rule is that a bulk delete is **all or nothing**. Before deleting anything, QRtub checks whether any Link in the selection belongs to a print batch that has moved past Draft. If even one does, the whole operation is rejected and nothing is deleted. You never end up with a partially deleted selection and no clear record of which rows went. That check makes a large bulk delete a slightly awkward instrument: one printed code in a selection of two thousand blocks the lot. Narrow the filter — for example to unassigned Links only — or unassign rather than delete. ## Working at real scale * Bulk actions run in chunks behind the scenes, so tens of thousands of Links is a supported size rather than a stress test * Selection resets after each action completes, and the list refreshes * If an operation fails, it fails as a whole with a message; it does not half-apply ## Related * [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links) — the three outcomes in detail, including automatic release * [Downloading QR Codes](/bulk-links/downloading-qr-codes) — the fourth bulk action * [Bulk Link Import via CSV](/bulk-links/csv-import) — bulk *editing* of destinations and fallbacks * [Adding and Removing Links in a Batch](/print-batches/editing-links) — batch membership, which the bulk menu doesn't cover # Bulk Link Import via CSV Source: https://help.qrtub.com/bulk-links/csv-import Creating and updating many Links from a spreadsheet: the six columns, what each link type requires, and the dry-run preview that runs before anything is written The CSV import on the Links page creates new Links and updates existing ones in one pass, up to 10,000 rows at a time. Every import runs as a preview first: QRtub reads the whole file, tells you how many rows would be created, updated or rejected and why, and writes nothing until you confirm. Use it when the addresses already exist somewhere else — a list of asset numbers from your maintenance system, a spreadsheet of destinations, an export you edited. ## The columns | Column | Purpose | | ------------------ | --------------------------------------------------------------------------------- | | `link_type` | Required. `random`, `numbered` or `custom` | | `url` | The slug. Required for numbered and custom; must be blank to create a random Link | | `destination_url` | Where the Link sends someone | | `fallback_url` | Where to send someone if a deep link doesn't open an app | | `fallback_message` | What to show instead if there's no fallback URL | | `is_active` | `true`/`false`, also accepts `1`/`0`, `yes`/`no`, `y`/`n`. Blank means active | This is exactly the shape the Links **Export** produces, so the fastest way to get a valid file is to export, edit, and import the same file back. Every column is read as text, which matters for numbered slugs: leading zeros in `cra0042` survive rather than being turned into `42`. `destination_url` can be a URL template with field bindings, like `app.com/inspect?id={{item.assetID}}`. Bindings are inserted exactly as stored with no URL-encoding, so a field containing a space or an `&` produces a broken address — check the fields you reference before importing hundreds of rows that use them. ## What each type needs on a create **Random** — leave `url` blank. QRtub mints the slug. A random row *with* a `url` is only ever an update; if that url matches nothing, the row is rejected rather than guessed at, with a message saying so. **Numbered** — `url` is required, and it must match a numbering pattern your team already owns. `cra0042` is accepted if you hold `cra` + 4 digits; otherwise the row is rejected with "does not match any numbering pattern owned by this team". The import does not claim new patterns for you. **Custom** — `url` is required and must satisfy the custom-slug rules: 3–50 characters, lowercase letters, digits, hyphens and underscores, not a reserved word, not already in use, and not inside a numbered pattern your team owns. ## How a row becomes an update instead of a create By its `url`. If the slug already exists on one of your team's Links, the row updates that Link instead of creating one — whatever `link_type` says. Matching follows each type's own case rules: numbered and custom slugs match without regard to case, random slugs match exactly. Only your team's Links are eligible. If you belong to several teams and a slug in the file exists in a different one, it is never treated as an update to that other team's Link. On an update, **columns absent from the file are left alone**, so a two-column file of `url,destination_url` will not wipe everyone's fallback settings. A column that is present but blank is treated as an instruction: a blank `destination_url` clears the destination, and a blank `fallback_url` or `fallback_message` clears that value. ## The dry run Choosing **Import** and picking a file runs the preview automatically. It performs the same classification and the same checks as the real thing — pattern matching, reserved-by-pattern, the random-slug rule, and duplicate detection — without writing anything, so the created and updated counts you see are honest rather than optimistic. Two rows creating the same new slug are caught here too: the first is counted, the second is rejected as a duplicate. Without that, the preview would promise two Links and the commit would deliver one plus an error. Confirm, and QRtub re-posts the same file to commit it. Rows that fail at this point — a custom slug that turned out to be taken, for instance — are reported individually and **do not stop the rest of the import**. You get a count of what landed and a per-row list of what didn't, so you can fix those rows and re-import just them. ## Limits * 10 MB per file, 10,000 rows, and the filename must end in `.csv` * Rows are processed one at a time, so a very large file takes a while — leave the tab open * The importer cannot assign Links to Items, add them to a print batch, or claim numbering patterns; it handles the Link's own slug, destination, fallbacks and active state only ## Related * [Bulk Assigning, Unassigning, and Deleting Links](/bulk-links/assign-unassign-delete) — attaching imported Links to Items afterwards * [Numbered Links](/links/numbered-links) — claiming the pattern a numbered import needs * [Custom Links](/links/custom-links) — the full slug rules the importer enforces * [App Links & Fallback URLs](/destinations/app-links) — what the two fallback columns are for # Downloading QR Codes Source: https://help.qrtub.com/bulk-links/downloading-qr-codes Getting QR code images out of QRtub: the panel for one code, the ZIP for many, and the file settings behind the door — format, error correction, transparency and one size per batch QRtub generates QR code images from your Links on demand. One Link gives you a panel showing the code; several give you a ZIP. The defaults are chosen for a Tag that has to last, so most exports need nothing changed. Everything adjustable sits behind **Change QR code file settings**. For what each setting does and when to deviate, see [QR Code Standards](/suppliers/qr-code-standards). ## One code Open a Link's row menu and choose **QR Code**. You get a panel showing the code itself, its full address with a **Copy** button, and **Download** as a secondary action. Scan it straight off the screen to check where the Link goes — usually faster than downloading a file to look at it. The address shown is exactly what the code encodes, scheme included: `https://qrtub.com/bar002` for a numbered or custom Link, `https://qrtub.com/r/x5fgd` for a random one — not the slug on its own. So what you copy and what someone scans are the same string, and Download gives you a file named after the slug, like `qr-code-bar002.svg`. ## Downloading many at once Select the Links you want and choose **Download QR Codes** from the bulk menu. The dialog shows how many codes are about to be produced. With more than one selected you always get a ZIP named for the day, like `qr-codes-2026-09-02.zip`, containing one file per Link named the same way as a single download. There is no option to receive many separate files instead. Because the filenames carry the slug, they line up with the **Short URL** and **Full URL** columns of an exported print list — which is how a supplier matches each image to its data row. Neither column is a byte-for-byte match for the filename, though: **Short URL** adds a leading slash and, for random Links, an `/r/` prefix, and **Full URL** adds the protocol and domain. Whoever does the matching has to strip those. The images are generated in your browser, in batches of fifty, with a progress toast counting up as it goes and a packaging step at the end. A few dozen codes is instant. Several thousand takes minutes, and the tab has to stay open for the whole time — if you close it, you get nothing and have to start again. If you used "select all", QRtub fetches the full matching set of Links first, so the total you see counts every match, not just the page on screen. ## What you can change The dialog opens with no controls — it states what you are about to get, and everything else sits behind **Change QR code file settings**. The defaults suit a durable Tag, so most exports need nothing touched. **Format — SVG or PNG.** SVG is the default: sharp at any size and fast for bulk downloads. Choose PNG when the software receiving it does not support SVG — Google Docs and Slides, most email clients, and a lot of label-printer software. Large PNG batches take longer to generate. **Error correction — L, M, Q or H.** The percentage is roughly how much of the code can be damaged while it can still be read: 7%, 15%, 25% and 30%. **Q is the default**, and right for anything produced as a physical Tag. Higher levels give more protection but may require a larger or denser code. See [QR Code Standards](/suppliers/qr-code-standards). **Transparent background.** Off by default. It removes the code's background so it can sit over other artwork — only take it when you control what ends up behind the code, because the white background is what guarantees the quiet zone. **Same size for every code.** On for a multi-code export. Addresses differ in length, so codes in one batch can come out at different module counts; pinning them to one size means a single Tag size scans the same across the whole batch. ## What you cannot change Worth being explicit about, because most QR generators expose these: * **PNG size is fixed** at 1024 × 1024 pixels. Not adjustable — but SVG makes it mostly moot, since vector art has no fixed size. * **Colors are fixed** at black on white, apart from turning the background off. * **The quiet zone is fixed** at 4 modules, which is what print specifications ask for. It is not a setting because there is no good reason to reduce it. * **Nothing is added to the image.** No logo, no caption, no border, no slug printed underneath. Whatever surrounds the code is your layout's job — and a logo belongs beside the code rather than inside it, for reasons covered in [QR Code Standards](/suppliers/qr-code-standards). ## Related * [QR Code Standards](/suppliers/qr-code-standards) — which format and error-correction level to choose * [Bulk Assigning, Unassigning, and Deleting Links](/bulk-links/assign-unassign-delete) — how selection and "select all" work * [Quiet Zone and Minimum Size](/suppliers/quiet-zone-and-size) — the clear space and minimum size a printed code needs * [Matching QR Codes to Data Rows](/suppliers/matching-codes-to-rows) — how these filenames pair each image with its CSV row # Collection Details Source: https://help.qrtub.com/collections/collection-details The four general settings — name, what one Item is called, description and cover image — where each one shows up, and their collection.* bindings Four settings identify a Collection: its name, a word for what one of its Items is called, a free-text description, and a cover image. They are all in **Settings → General**, under **Collection details**. None of them change how anything behaves. They are display values — but they are also *bindable*, which is the part people miss (see below). ## Name The only required one. It appears in the Collections list, in the sidebar, and as the heading above the Item grid, and it is used to name the file when you export a backup (`heavy-equipment-2026-08-22.json`). **Renaming is free.** Nothing is derived from the name — no URL, no Item data, no Link address — so you can rename a Collection at any time without consequence. You can rename inline from the grid heading as well as from settings. ## What is one Item called? An optional singular word for one Item in this Collection — "Machine", "Vehicle", "Room". Use the singular, not the plural. It shows on the Collection's card in the Collections list and dashboard, and it feeds the `{{collection.items_name}}` binding used as the subtitle on the built-in default page. Leaving it blank is fine; nothing falls back to a broken label. ## Description Free text describing what the Collection is for. It shows in the Collections list, is searchable there, and is bindable on pages. Nobody outside your team sees it unless you put it on a page. ## Cover image An image file, up to **2 MB**. It shows beside the Collection's name in the sidebar, so it is read at roughly icon size — a simple, high-contrast image works better than a detailed photo. Uploading a new image replaces the old one when you save; if the upload fails, the previous image is kept and the rest of your changes still save. ## Using these in bindings All four are available to page sections and Destination URLs: | Binding | Value | | ---------------------------- | ---------------------------------- | | `{{collection.name}}` | The Collection name | | `{{collection.description}}` | The description | | `{{collection.items_name}}` | The "what is one Item called" word | | `{{collection.image_url}}` | The cover image URL | One caution if you put `{{collection.name}}` inside a Destination URL: values are inserted exactly as stored, with **no URL encoding**. A Collection named `Site A & B` will break the link it is inserted into. Keep names you intend to use in URLs free of spaces, `&`, `?` and `#`. ## Related * [What Is a Collection?](/collections/overview) * [Creating a Collection](/collections/creating-a-collection) * [Default Destination for New Items](/collections/default-destination) * [Exporting a Collection Backup](/collections/export-backup) # Creating a Collection Source: https://help.qrtub.com/collections/creating-a-collection The one-step creation fork — one destination or several, or a starter template — plus the auto-generated name and where the page template comes from Creating a Collection is a single click. There is no multi-field setup form: you answer one question about what scanning an Item should do, the Collection is created immediately, and everything else is editable afterward from its settings. Open the Collections list and choose **Create**, or use the **+** button beside the Collections list in the sidebar. ## The two choices on the creation screen Both cards create the Collection straight away and drop you into its (empty) Item grid. | Choice | What it sets up | | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Connects to one destination** | Each Item's Link goes straight through to a single Destination — Direct Mode. Pages stay off, and the Collection gets a **Default destination** setting for new Items. | | **Connects to several** | Each Item's Link opens a page listing several Destinations — Page Mode. This turns pages on for the Collection and reveals the page tab in its settings. | Under the cards, the same screen offers a short strip of starter templates plus **Browse all**. Picking a template replaces this choice — the template carries its own scan behavior, field schema and page design. See [Starter Templates](/collections/starter-templates). Neither choice is permanent. You can flip a Collection between the two later from its settings; see [Scan Behavior for New Items](/collections/scan-behavior-default). ## The name you get The new Collection is named sequentially — one past the highest numbered default the team already has, so deleting one in the middle never produces a name collision (Collection 1, 2, 3 → delete 2 → the next one is 4). One wrinkle worth knowing: Collections were renamed from "Tubs", and the name *generator* still uses the old word, so the name you actually see is `Tub4`, not `Collection4`. Rename it inline from the grid header or from **Settings → General** — nothing is derived from the name, so renaming is free at any time. ## What a fresh Collection starts with * **Four fields** — name, Item ID, description and tags. Everything else you add yourself. * **Random link generation** — a fresh `qrtub.com/r/x5fgd`-style Link is minted and attached automatically each time you add an Item. Change this in **Settings → Link generation**. * **No page template of its own.** A Collection created from one of the two cards has no stored page design. Until you build one in the Page Editor, Items in Page Mode render a built-in default page — the Item's name, image, status and tags, plus the Collection's own name, description and image. Collections created from a starter template *do* get a real page template, generated from that template's fields. * **No sample Items.** Only starter templates seed example data. Collections that predate the link-generation setting behave differently: their default is to mint no Link at all. Only Collections created through the current flow start on random. ## If you only want to print codes If you have nothing to catalog yet and just need codes on physical items, you do not need a Collection first. The creation screen has a **Start with physical codes** link that takes you to Links instead, where you can generate and print Links now and attach them to Items whenever the Items exist. A Link can live on a QR code, an NFC tag or a plain short URL. ## Related * [Starter Templates](/collections/starter-templates) * [Collection Details](/collections/collection-details) * [Link Generation for New Items](/collections/link-generation-modes) * [Scan Behavior for New Items](/collections/scan-behavior-default) # Default Destination for New Items Source: https://help.qrtub.com/collections/default-destination The URL template every new Item in a pass-through Collection starts with — built with field tokens, previewed against a real Item, and stamped at creation A Collection in Direct Mode can carry a **Default destination**: one URL template that every new Item starts with, so you configure the destination once instead of 500 times. It sits in **Settings → Scan behavior**, directly under the scan toggle, and only appears when pages are off — a Collection whose Items open a page has no single destination to default. ## Building the URL Type the URL and insert field tokens where the Item's own data belongs. Typing `item.` offers the Collection's fields, and inserts them as `{{item.field_key}}`: ```text theme={null} https://safetyculture.com/asset/{{item.safetyculture_asset_id}} ``` With a real Item's data, that resolves to `https://safetyculture.com/asset/AST-4471`. The builder previews the result live against **a real Item from this Collection** — not a mock. It picks an Item that has a value for every field the template references, so the preview shows a URL that actually resolves; if no Item has all of them, it uses the first one. Two rules to keep in mind, because neither produces an error: * **Values are inserted exactly as stored, with no URL encoding.** A field containing a space, `&`, `?` or `#` produces a broken link. Keep the fields you use inside URLs free of those characters. * **A missing or empty field inserts an empty string**, so the URL is still built — just wrong. That is what the warning below is for. ## The missing-value warning If the template references a field that some Items have left blank, a warning appears naming the field and counting them: *"Uses Serial, but 12 of 40 items don't have a value yet — their codes won't resolve until filled,"* with a link straight to the Item grid. Take it seriously before a print run. Those Items have QR codes that will resolve to a truncated URL, and nothing about the code itself will look wrong. ## App links and their fallback If the default destination is an app deep link (`myapp://…`) rather than a web URL, the builder adds a fallback pair: a web URL to send people to, and a message to show, when the app is not installed. Both belong to this default and are stamped onto new Items alongside it. Remove the default destination and the fallback pair is cleared with it, so a stale fallback can never quietly reactivate later. ## Stamped at creation, never read at scan This is the one behavior worth being precise about. The default is **copied onto each Item when the Item is created**. Adding an Item through the form prefills its destination with the Collection default, where you can edit or clear it before saving; CSV imports and API calls get the same copy applied when the row does not supply a destination of its own. Two consequences follow: 1. **Editing the Collection default is not retroactive.** Existing Items keep the copy they were created with. To change many Items at once, update them — CSV export, edit the destination column, re-import. 2. **There is no scan-time fallback.** Nothing looks up the Collection default when a code is scanned. An Item whose own destination is blank resolves to nothing, by design. This is the one exception to how field defaults normally work; see [Field Defaults](/fields/field-defaults) for the general rule. ## Related * [Scan Behavior for New Items](/collections/scan-behavior-default) * [Field Bindings & URL Templates](/destinations/field-bindings) * [Field Defaults](/fields/field-defaults) * [App Links & Fallback URLs](/destinations/app-links) # Deleting a Collection Source: https://help.qrtub.com/collections/deleting-a-collection What deleting a Collection permanently removes, why your printed QR codes keep working anyway, and what to export before you confirm Deleting a Collection permanently removes the Collection, every Item in it, and its page design. The Links those Items were using are **released, not deleted** — so QR codes already printed and installed keep working. The action is in **Settings → Admin → Danger zone → Delete**. A confirmation dialog states the same thing before it runs. ## What is permanently gone * **The Collection itself**, including its field schema and all its settings * **Every Item in it** — all field values, and any page override saved against an individual Item * **The page template**, including its version history There is no archive, no trash and no undo. Collections have no "archived" state to fall back on: once confirmed, the records are removed from the database immediately. ## What survives **The Links.** Every Link that was assigned to an Item in this Collection is unassigned first and returned to your unassigned pool, and only then is the Collection deleted. That order is deliberate — it is what keeps a plaque bolted to a machine from becoming a dead code. Each of those Links keeps its address, still resolves, and can be assigned to a new Item whenever you are ready. That means deleting a Collection is recoverable in the one way that matters physically: you lose the data, you do not lose the printed codes. For what a released Link does in the meantime and how to reassign one, see [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links). **Print batches.** Any print batch that was created from this Collection stays, along with its stored CSV and per-code installation status. It simply loses the "made from this Collection" association. **Team-level things.** Numbered link patterns your team reserved stay reserved, and remain available to other Collections. Team members, billing and other Collections are untouched. ## Before you confirm 1. **Export the Items to CSV** from the Item grid. This is the only way to keep them — and note that a [Collection backup](/collections/export-backup) will *not* help here, because backups deliberately exclude Items. 2. **Export a Collection backup** if you may want the structure again — the fields, settings and page design. That file can later recreate the Collection as a new one. 3. **Check whether codes are installed.** They will keep resolving, but each released Link needs reassigning before it points anywhere useful again. If there are hundreds, plan that work before you delete rather than after. If your real goal is a clean slate rather than removal, changing the field schema and page design in place is usually less disruptive than deleting — the Items and their Link assignments stay intact throughout. ## Related * [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links) * [Exporting a Collection Backup](/collections/export-backup) * [Exporting Items to CSV](/import-export/exporting-items) * [What Is a Collection?](/collections/overview) # Exporting a Collection Backup Source: https://help.qrtub.com/collections/export-backup Downloading a JSON snapshot of a Collection's settings, field schema and page template — and why its Items are deliberately not in the file A Collection backup is a single JSON file you download on demand. Open **Settings → Admin → Backup & restore**, choose **Manage backup**, then **Download Backup**. The file is named after the Collection and the date, like `heavy-equipment-2026-08-22.json`. ## What is in the file * **Details** — name, description, cover image and the "what is one Item called" label * **The full field schema** — every field, its type, labels, allowed values, defaults and required flags * **Collection settings** — link generation mode and Item ID mask, scan behavior default, default destination * **The active page template** — the page design Items in this Collection render * **Per-Item page overrides** — any page customization saved against an individual Item ## What is not in the file **Items are not included.** This is the one thing everyone assumes and it is worth being blunt about: a Collection backup captures the *shape* of a Collection, not its contents. Restoring one will not bring your equipment records back. Export Items separately as CSV from the Item grid. Keep the two files together if you are archiving a Collection properly — the JSON restores the structure, the CSV restores the rows. Also absent: Links (they belong to the team, not the Collection, and survive independently), print batches, and anything team-level such as members or billing. Because Items are excluded, the per-Item page overrides in the file are recorded against an Item identifier rather than an internal database ID. They reattach only if Items with matching identifiers exist wherever you import the file — otherwise they are skipped with a warning. ## When to take one * **Before a destructive change** — reworking a field schema, or replacing a page design you may want back. * **To reuse a setup** — a finished Collection exported as a backup becomes your own reusable starter, better fitted than any system template. See [Creating a New Collection From a Backup](/collections/new-collection-from-backup). * **To move a setup to another team** — the file has no team baked into it; you choose the team when you import. Backups are manual and on demand. Nothing is scheduled, and QRtub does not keep old versions of this file for you — the copy you download is the copy you have. ## Related * [Importing a Collection Backup](/collections/import-backup) * [Creating a New Collection From a Backup](/collections/new-collection-from-backup) * [Exporting Items to CSV](/import-export/exporting-items) * [Deleting a Collection](/collections/deleting-a-collection) # Importing a Collection Backup Source: https://help.qrtub.com/collections/import-backup Restoring a backup file into an existing Collection: what Merge adds, what Replace destroys, and why Replace is riskier than the confirmation says Importing restores a backup file into a Collection that already exists. Open **Settings → Admin → Backup & restore → Manage backup**, pick an import mode, then choose the `.json` file. A confirmation step lists what will happen before anything is written. There are two modes and they are not variations on a theme — one is additive, the other deletes data. ## Merge — additive Merge compares the backup's fields against the Collection's and **adds only the fields that are missing**. Fields the Collection already has are left exactly as they are: same type, same labels, same allowed values, same defaults. Nothing is overwritten and no Item data is touched. What Merge does *not* leave alone is the page design. **If the backup contains a page template — and it almost always does — that template replaces the Collection's current one.** The confirmation step says as much ("Update page template if included"), and it is easy to skim past. If you only want the fields, export a backup of the current page design first so you can put it back. Collection details — name, description, cover image, Items label — are untouched by Merge. ## Replace — destructive Replace overwrites the Collection from the backup: details, the entire field schema, and the page template. You have to type `REPLACE` to confirm it, and it cannot be undone. **It also deletes every Item in the target Collection, along with their per-Item page overrides.** The in-app note beside this option says Items are not affected. That note is wrong: the Items in the Collection you are importing *into* are deleted before the backup is restored. The backup itself carries no Items to put back in their place (see [Exporting a Collection Backup](/collections/export-backup)), so the practical result is an empty Collection with the backup's structure. Two consequences to take seriously before you type `REPLACE`: * **Export your Items to CSV first.** It is the only copy of them you will have. * **Deleted Items do not release their Links.** Deleting an Item or a whole Collection through the normal path releases its Link back to your unassigned pool so printed codes keep working. This path does not — a Link attached to one of these Items goes with it. If the Collection has codes in the field, do not use Replace; import into a new Collection instead. If what you actually want is "this backup, as a fresh Collection," use [Creating a New Collection From a Backup](/collections/new-collection-from-backup). It is safe by construction — nothing existing is involved. ## What both modes tell you afterward A summary reports what changed: whether the Collection's settings were updated, how many new fields were added, and whether the page template was replaced. Warnings appear in the same dialog rather than silently — the ones worth reading are: * **A version mismatch**, if the file came from an older export format. The import still runs. * **Overrides that found no matching Item.** Per-Item page overrides are matched by Item identifier, so an override whose Item does not exist in the target is skipped and named. * **Skipped rows**, in the rare case a hand-edited backup carries an `items` array and one of those Items collides with an existing Item ID. The rest still import. Only `.json` files are accepted, and a file that is not a valid backup is rejected before anything is written. ## Related * [Exporting a Collection Backup](/collections/export-backup) * [Creating a New Collection From a Backup](/collections/new-collection-from-backup) * [Exporting Items to CSV](/import-export/exporting-items) * [Deleting a Collection](/collections/deleting-a-collection) # Building an Item ID Mask Source: https://help.qrtub.com/collections/item-id-mask The prefix, digit-count and suffix editor behind ID-based link generation — free-form masks vs. reserved numbered patterns, and the conflict rules for each When a Collection mints ID-based Links, the *mask* is what turns an Item ID into a Link address. It is three parts — a prefix, an optional digit count, and a suffix — and the editor appears inline the moment you select **Create an ID-based link** in **Settings → Link generation**. The editor shows a live preview of the address it will produce, so you can see the result before saving: `qrtub.com/CRA####TL` for a numbered mask, or `qrtub.com/cratl` for a free-form one. ## Two shapes, one editor The digit count is what separates them, and the difference matters more than it looks. ### A numbered pattern (digit count set) Setting a digit count between 1 and 10 turns the mask into a **reserved numbered pattern**: prefix, exactly that many digits, suffix. `CRA` + 4 + `TL` produces the template `CRA####TL`, which an Item ID must match exactly — `CRA0042TL` passes, `CRA42TL` and `CRA0042` do not. This is enforced, not suggested: * The Item form prefills the Item ID box with the template (`CRA####TL`) so you only type the number into the `#` slots. * The format is checked **on the server** on both create and edit, so CSV imports and API calls are held to it too, not just the form. * Matching is case-insensitive, and the affixes are stored exactly as you type them. **Saving a numbered mask reserves that pattern for your team.** It then appears in the numbered patterns your team owns, and its number pool is shared. ### A free-form mask (digit count blank) Leave the digits blank and the affixes simply wrap whatever Item ID you type: ``, lowercased. Nothing about the Item ID's shape is enforced. This is the older behavior, kept so existing Collections do not change. Use it when you already maintain an ID scheme of your own — a manufacturer's serial, an accounting code — and just want the Link to mirror it. ## Adopting a pattern the team already has If your team has reserved numbered patterns already, the editor lists them in a dropdown with each one's next available number, so a second Collection can join an existing scheme instead of inventing a parallel one. Pick one and the prefix, digits and suffix fill themselves in. Once the mask matches a pattern the team owns, the editor shows its usage: the next number, the total generated, how many are currently active, which numbers are used, and which numbers are free in the gaps. That last one is the useful column — deleted Items leave their numbers behind, and this is where you see them. For what a numbered pattern is in its own right, and how claiming a range works outside a Collection, see [Numbered Links](/links/numbered-links). ## Conflict rules The two mask shapes behave in opposite ways here, which is the single most surprising thing on this page. **A free-form mask can only belong to one Collection per team.** Try to save affixes another Collection on your team already uses and the save is refused, naming the Collection that has them. The reason is mechanical: a free-form mask has no shared number pool to coordinate with, so two Collections using the same affixes would race each other for the same addresses. **A numbered pattern is deliberately shareable.** Several Collections on the same team can adopt the same pattern, because they draw from one pool with shared used-number tracking, and each Item takes an unused number. Adopting a pattern is never blocked by another Collection. **A pattern reserved by a different team is refused.** Numbered patterns are globally unique, so if another team holds `CRA####TL` you will be asked for different affixes or a different digit count. ## Failure modes worth knowing * **A number already taken by another Item** stops the Link, and the Item is still created without one. Pick an unused number — the gaps list shows which are free. * **An unattached Link at that address is adopted**, not duplicated. This is how a pre-printed numbered code gets picked up automatically when you create the matching Item. * **A blank Item ID mints no Link.** The Item form requires one, but paths that can leave it blank — duplicating an Item, for instance — produce an Item with no Link rather than an error. ## Related * [Link Generation for New Items](/collections/link-generation-modes) * [Numbered Links](/links/numbered-links) * [Item ID](/items/item-id) * [Choosing a Link Type](/links/choosing-a-link-type) # Link Generation for New Items Source: https://help.qrtub.com/collections/link-generation-modes The Collection setting that decides whether a Link is minted automatically when an Item is created — random, built from the Item ID, or none at all Every Collection has one rule for what happens the moment you add an Item: mint a Link and attach it automatically, build the Link's address from the Item's own Item ID, or create no Link at all. Set it in **Settings → Link generation**, under **When a new item is created**. Items and Links are separate records. This setting is only about convenience at creation time — it never restricts what you can attach to an Item later. ## The three modes ### Create a random link A fresh Link like `qrtub.com/r/x5fgd` is minted and attached to the Item automatically. You do not choose the address, and there is nothing to configure. This is the default for Collections created through the current flow, and the right choice when you are adding Items first and printing codes afterward. ### Create an ID-based link The Link's address is built from the Item's own Item ID, wrapped in a prefix and suffix you define — so an Item ID of `CRA0042TL` becomes `qrtub.com/cra0042tl`. If that address already exists but is unattached (a pre-printed code, for instance), the existing Link is adopted rather than a duplicate minted. This mode has its own editor, including an option to fix the digit count so the whole team shares one numbered format. See [Building an Item ID Mask](/collections/item-id-mask) for how to set it up and what it then requires of every Item ID you type. ### Don't create a link Items start with no Link. Attach one later from the Item, or scan a pre-printed code in the field and match it up then. This is the sensible setting while you are still building out a Collection, and it is the default for Collections created before this setting existed — so an older Collection that mints nothing is behaving correctly, not broken. ## What the setting does not do **It is not retroactive.** Changing the mode affects Items created from that point on. Items that already exist keep whatever Link they have, or keep having none. **It does not govern deletion.** Deletion behavior is fixed and not configurable: deleting an Item (or a whole Collection) releases its Link back to your unassigned pool instead of destroying it, so printed codes keep working and can be reused. See [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links). ## When minting fails Random mode has nothing to fail on. ID-based mode does — an Item with a blank Item ID, an Item ID that does not match the Collection's required format, or an address already attached to a different Item all stop the Link from being created. **The Item is still created.** QRtub saves the Item and reports the reason the Link could not be built; it does not roll the Item back. Fix the Item ID or attach a Link by hand, then carry on. It is worth reading that message rather than dismissing it, because an Item with no Link looks completely normal in the grid. ## Related * [Building an Item ID Mask](/collections/item-id-mask) * [Item ID](/items/item-id) * [Random Links](/links/random-links) * [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links) # Creating a New Collection From a Backup Source: https://help.qrtub.com/collections/new-collection-from-backup Spinning up a brand-new Collection from a backup file — the preview step, the automatic (Copy) name, and why this is QRtub's closest thing to duplicating a Collection A backup file can create a brand-new Collection instead of restoring into an existing one. On the Collections list, choose **Import Backup** (next to the create button), pick a `.json` backup, and confirm. Nothing existing is touched, which makes this the safe way to use a backup file. ## The preview step Before anything is created, a preview shows you what is in the file: * The name the new Collection will get * How many fields it defines * The page template it carries, if any * The description, if the file has one Confirm and the Collection is created in your currently active team, then you land on its settings so you can rename it and look over what came across. If you want it in a different team, switch teams first. ## The name gets " (Copy)" The new Collection is named after the one in the backup with `" (Copy)"` appended — `Heavy Equipment (Copy)`. This is automatic and not optional, so renaming is usually the first thing you do. Nothing is derived from a Collection's name, so renaming costs nothing. ## This is how you duplicate a Collection There is no **Duplicate** button anywhere in QRtub. This flow is the equivalent, in two steps: 1. Export a backup of the Collection you want to copy. 2. Import that file here. The copy arrives with the same field schema, the same details, the same link-generation and scan settings, and the same page design as the original. **It does not arrive with the original's Items** — Collection backups never contain Items. If you want the Items too, export them as CSV from the source Collection's grid and import that CSV into the copy. ## One thing to check on the copy If the source Collection built ID-based Links from a *free-form* Item ID mask (a prefix and suffix with no digit count), the copy is created carrying the same affixes — and a free-form mask can only belong to one Collection per team. Creating the copy does not complain, but the first time you save its link-generation settings you will be asked to pick different affixes. Reserved numbered patterns are exempt: several Collections can share one. See [Building an Item ID Mask](/collections/item-id-mask). ## Related * [Exporting a Collection Backup](/collections/export-backup) * [Importing a Collection Backup](/collections/import-backup) * [Starter Templates](/collections/starter-templates) * [Building an Item ID Mask](/collections/item-id-mask) # What Is a Collection? Source: https://help.qrtub.com/collections/overview The entity that groups Items under one shared field schema, one link-generation rule, one scan default and one page design — and what deliberately sits outside it A Collection is a group of Items that share the same set of fields, the same page design, and the same rule for how new Links get created. A Collection is more than a folder. Putting Items in the same Collection is what makes them share a structure — add a "Service Hours" field to the Collection and every Item in it has that field. That shared structure is the point; the grouping is a side effect. Every Item belongs to exactly one Collection. An Item cannot exist without one, which is why creating a Collection is the first thing you do in QRtub. ## What a Collection owns Five things are set once on the Collection and then apply to every Item inside it: | Setting | What it decides | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Fields** | The columns every Item carries — the four core fields plus any custom fields you define. See [Core Fields vs. Custom Fields](/fields/core-vs-custom). | | **Link generation** | Whether a Link is minted automatically when an Item is created, and how its address is built. See [Link Generation for New Items](/collections/link-generation-modes). | | **Scan behavior** | Whether a new Item starts in Direct Mode (straight to one Destination) or Page Mode (opens a page of several). See [Scan Behavior for New Items](/collections/scan-behavior-default). | | **Page template** | The one page design every Item in the Collection renders when scanned, unless that Item has its own override. | | **Details** | Name, description, what to call one Item, and a cover image. See [Collection Details](/collections/collection-details). | Two of these are defaults rather than rules: scan behavior and field default values can be overridden on an individual Item. The field schema, the link-generation rule and the page template apply Collection-wide. ## What sits outside a Collection **Links live at the team level, not inside a Collection.** A Link can be created, printed and installed before any Item exists, and later assigned to an Item in any Collection on the team. That separation is what makes the print-first workflow possible — and it is also why deleting a Collection does not destroy its Links. **Teams own Collections.** A Collection belongs to one team, and everything team-scoped — members, billing, reserved numbered link patterns — is shared across all of that team's Collections. ## Typical Collections * **Heavy Equipment** — fields for serial number, make, model, service hours, site * **Meeting Rooms** — room number, floor, capacity, AV equipment * **Fire Safety Equipment** — type, location, inspection due, certification number Splitting by Item type rather than by site or client is usually right: Items in one Collection have to make sense sharing one set of fields and one page design. ## Related * [Creating a Collection](/collections/creating-a-collection) * [Starter Templates](/collections/starter-templates) * [Collection Details](/collections/collection-details) * [Deleting a Collection](/collections/deleting-a-collection) # Scan Behavior for New Items Source: https://help.qrtub.com/collections/scan-behavior-default The Collection toggle that decides whether a new Item's scan passes straight through to one Destination or opens a page of several One toggle in **Settings → Scan behavior** decides what scanning an Item does by default: **Show a profile page**. * **On** — a scan opens the Item's page, which can offer several Destinations. This is Page Mode. * **Off** — a scan goes straight to a single Destination, with no page in between. This is Direct Mode, and it makes a **Default destination** setting appear below the toggle. ## It is a default, not a rule This sets the starting point for new Items. Any individual Item can be switched to the other mode from its own settings, and that explicit choice always wins over the Collection. The corollary matters: an Item that has *never* made an explicit choice follows the Collection. Flipping this toggle changes how those Items resolve, including Items that already exist — most often Items created by CSV import, which do not record a per-Item choice unless you give them one. ## What changes in the interface Turning the toggle on reveals the Collection's page tab in settings, where you can preview the page design and open the Page Editor. Turning it off hides that tab — and if you were sitting on it, you land back on **Scan behavior**. The page design itself is not deleted; it is still there if you turn pages back on. Turning pages off is also what surfaces the [Default Destination for New Items](/collections/default-destination) builder, since a pass-through Item needs somewhere to send the scan. ## Privacy is per-Item, not per-Collection A related setting people look for here and do not find: there is no Collection-level control for whether pages require sign-in. Privacy is set on the individual Item. New Items start public. ## Choosing between them Direct Mode is right when a scan has exactly one sensible outcome — a product page, an asset record in one system, a form. It is the fastest path for the person scanning: no page, no tap. Page Mode is right when one physical code has to serve more than one purpose or more than one audience — an inspection app for the operator, a manual for the technician, a support form for a customer. One code, several Destinations, no second sticker. For a full comparison of the two modes, see [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode). ## Related * [Default Destination for New Items](/collections/default-destination) * [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode) * [Pages Overview](/pages/pages-overview) * [What Is a Collection?](/collections/overview) # Starter Templates Source: https://help.qrtub.com/collections/starter-templates The eight ready-made setups that seed a new Collection's fields, page design and sample Items — available at creation time only A starter template is a ready-made Collection setup. Picking one at creation time seeds three things at once, so you get a working Collection with a real page instead of four empty fields. Templates appear on the creation screen (the first five, as examples) and in the full library behind **Browse all**, which has a search box. Choosing one creates the Collection immediately — there is no configuration step in between. ## What a template seeds * **A field schema** — the custom fields that Item type needs, already typed, labeled and ordered. An inventory template arrives with SKU, supplier, quantity, reorder level and unit cost; you are not defining those by hand. * **A page template** — a real page design generated from those fields, ready to open in the Page Editor. * **Three sample Items** — filled-in examples so the grid and the page preview show something meaningful on day one. Delete them once you have real data; they are ordinary Items. The template also sets the Collection's scan behavior. A template built around a page turns pages on and defaults new Items to Page Mode; a pass-through template leaves pages off and defaults new Items to a single Destination. ## The eight templates | Template | What it sets up | New Items default to | | -------------------------------- | ------------------------------------------------------------------------------------------ | -------------------- | | **SafetyCulture asset QR codes** | Connects each asset to its record in the inspection platform | Direct Mode | | **Clone a QR code** | Points a QRtub Link at the same place an existing code already goes | Direct Mode | | **Equipment + inspections** | Connects each machine to all of its systems from one page | Page Mode | | **Audience routing** | Offers staff and customer Destinations side by side on one code, for the scanner to choose | Page Mode | | **Branded handoff** | A branded page whose main button goes to one destination | Page Mode | | **Inventory management** | Stock levels, suppliers, storage location, logistics | Direct Mode | | **IT asset tracking** | Computers and devices with lifecycle details on one page | Page Mode | | **Medical equipment** | Calibration, compliance and service records | Page Mode | The first five are the ones shown as examples on the creation screen; all eight are in the library. The platform behind the SafetyCulture template is now called Mitti — the template name still uses the older name. ## Templates apply once, at creation **A template is a starting point, not a live link.** Once the Collection exists, there is no way to switch it to a different template, and nothing about the template keeps applying — the fields, the page and the sample Items are now ordinary Collection content you own and can change freely. That means: * Editing a field the template created is safe. It is your field now. * Deleting the sample Items does not break the page template. * If you picked the wrong template, the practical fix is a new Collection from the right one rather than a conversion. Nothing is lost if the wrong one is still empty. If you want a *reusable* starting point of your own rather than a system template, export a finished Collection as a backup and create new Collections from that file — see [Creating a New Collection From a Backup](/collections/new-collection-from-backup). ## Related * [Creating a Collection](/collections/creating-a-collection) * [What Is a Collection?](/collections/overview) * [Creating a Custom Field](/fields/creating-a-field) * [Creating a New Collection From a Backup](/collections/new-collection-from-backup) # Creating Your First Link Source: https://help.qrtub.com/creating-your-first-link A worked end-to-end path: create a Collection, add an Item, get a Link, download its QR code, and give it somewhere to go. This walks one complete path from an empty account to a QR code you can print and scan. It is not the only order that works — Collections, Items, Links and Pages are independent, so creating a hundred Links first and connecting them months later is equally valid. **Before you start:** you need a QRtub account and a team selected in the team switcher at the top of the sidebar. Parts of the app still say "tub" where these docs say "Collection" — the entity was renamed and the labels have not all caught up. ## Create a Collection In the sidebar, click the **+** next to the section labeled **Tub** — the old name for Collections, still on the button. The **New tub** screen it opens offers two cards — *Connects to one destination* and *Connects to several* — plus a row of starter templates. Picking any of them creates the Collection immediately. There is no form: the Collection gets an automatic sequential name (`Tub1`, `Tub2`, and so on) and you land on its empty grid, where the name, description and cover image are all editable in place. The two cards set what a scanned code does by default — pass through to one destination, or open a Page listing several — and that is changeable later in settings. ## Add an Item and get a Link Click **Add your first item**, give it a name, and save. Collections created this way default to random link generation, so QRtub mints a Link at the moment the Item is saved and confirms it with a message naming the new slug. To see it, open the Item and switch to its **Access Links** tab — the full URL is listed there, in the form `qrtub.com/r/x5fgd`. An Item can hold more than one Link. If a Collection's link generation is set to *None* — the default for older Collections — saving an Item mints no Link, and you attach one yourself as below. ## Or start from a Link you already printed Open **Access Link** in the sidebar and click **Create Link**. Choose a strategy — Random, Numbered, or Custom — and for Random you can create up to 100 in one request. Nothing needs to exist first: a Link with no Item and no destination is a valid, permanent, printable Link. To connect one, use the row menu on any Link and choose **Assign to Item**; the picker searches the whole team, so the Item can live in any Collection. An Item's **Access Links** tab works from the other direction, listing the team's unassigned Links so you can attach a pre-printed code there. ## Download the QR code From a Link's row menu, choose **Download QR Code**. You get a single PNG at 1024 px, black on white, with a 2-module quiet zone; select several Links first and you get a zip of PNGs instead. There is no SVG export and no error-correction setting today. ## Point the Link at something Open the Item and use the **Destination** tab to set where a scan goes, or the **Page** tab to build a screen with several Destinations. Either can be changed at any time without touching the printed code. A Destination can be a fixed URL or a template that inserts this Item's own field values, so one template serves every Item in the Collection. Values are inserted exactly as stored — no URL-encoding — so a field containing a space or an `&` breaks the resulting link. ## Related * [What a Link Is](/links/what-a-link-is) — the slug-to-destination model * [Choosing a Link Type](/links/choosing-a-link-type) — random vs. numbered vs. custom * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax and its rules * [The Print-First Workflow](/print-first/overview) — printing in bulk before the Items exist # App Links & Fallback URLs Source: https://help.qrtub.com/destinations/app-links Use deep links to open mobile apps directly, with automatic fallback when the app isn't installed QRtub Destinations support app deep links — special URLs that open a mobile app directly to a specific screen. When someone scans and the app isn't installed, QRtub automatically falls back to a URL you specify, keeping the experience useful rather than dead. ## What Are App Links? App links are URLs that use a custom scheme instead of `https://`. When a device recognizes the scheme, it opens the corresponding app. **Examples:** * `iauditor://template/new_audit/` — opens Mitti (formerly SafetyCulture) to a specific template * `myapp://asset/EXC-203` — opens a custom app to an asset record * `spotify://track/3n3Ppam7vgaVa1iaRUIOKE` — opens Spotify to a track These work great when the app is installed. The problem is when it isn't. ## The Problem: App Not Installed When someone scans a QR code and taps a Destination with an app link: * **App installed** — the device opens the app directly * **App not installed** — nothing happens, or the user sees an error Without a fallback, a scan that ends in a blank screen is a failed interaction. This is especially common during rollouts, when not everyone has the app yet, or when contractors scan equipment they don't normally manage. ## How QRtub Handles App Links QRtub detects when a Destination URL is an app link (any non-`https://` scheme). At scan time: 1. QRtub attempts to open the app link 2. A 2.5-second timer starts 3. **If the app opens** — the timer is canceled, the user is in their app 4. **If the page is still visible after 2.5 seconds** — the app wasn't installed, QRtub navigates to your Fallback URL If no Fallback URL is set, QRtub shows a message instead — either your custom Fallback Message, or a default "App not available" notice. ## Setting a Fallback URL When you add or edit a Destination with an app link URL, QRtub automatically shows a fallback configuration panel. **In the Destination editor:** 1. Enter your app link URL (e.g. `iauditor://template/new_audit/template_abc123`) 2. An amber notice appears: "This is an app link — set a fallback for users without the app installed" 3. Enter a **Fallback URL** — the web page to open if the app isn't available **Example (Mitti):** * App link: `iauditor://template/new_audit/template_fcbc86fd41a74180921347e4be53bdf2` * Fallback URL: `https://app.mitti.com/inspection/new?templateId=template_fcbc86fd41a74180921347e4be53bdf2` Users with Mitti installed go straight to the app. Users without it land on the web version — same form, different delivery. ## Setting a Custom Fallback Message If there's no web equivalent to fall back to, set a **Fallback Message** instead of a URL. **Example:** * App link: `myapp://asset/{{item.assetID}}` * Fallback Message: `"Please install the Asset Manager app from the App Store to access this equipment record."` When someone without the app scans, they see your message rather than a confusing blank screen. If neither Fallback URL nor Fallback Message is set, QRtub shows a default "App not available" notice. ## Using Bindings in Fallback URLs Fallback URLs support `{{item.field}}` bindings — the same way Destination URLs can include Item data automatically. **Example:** App link: ``` iauditor://template/new_audit/template_abc123?8f2f287e={{item.assetID}} ``` Fallback URL: ``` https://app.mitti.com/inspection/new?templateId=template_abc123&asset={{item.assetID}} ``` Configure both once. Roll out to 500 items. Each scan routes to the right app screen (or web equivalent) for that specific item — no per-item configuration. ## Where Fallback Settings Live Fallback URL and Fallback Message can be set at three levels: | Level | Where to set it | When it applies | | --------------- | ----------------------------------- | ---------------------------------------- | | **Destination** | In the Destination editor, per-rule | Most specific — overrides everything | | **Link** | In the Link settings | Applies to all Destinations on this Link | | **Item** | In the Item editor | Applies across all Links for this Item | The most specific setting wins. Destination-level fallback takes priority over Link-level, which takes priority over Item-level. ## Common Examples ### Mitti (iAuditor) **App link:** `iauditor://template/new_audit/{{item.templateID}}` **Fallback URL:** `https://app.mitti.com/inspection/new?templateId={{item.templateID}}` See the [Mitti Integration guide](/integrations/mitti/setup) for full setup instructions. ### Generic Enterprise App **App link:** `mycompanyapp://workorder/create?asset={{item.assetID}}` **Fallback URL:** `https://app.mycompany.com/workorders/new?asset={{item.assetID}}` **Fallback Message:** `"Open the MyCompany app to create a work order."` Set both Fallback URL and Fallback Message — QRtub uses the URL if set, otherwise shows the message. ### App Download Link (No Web Version) **App link:** `myapp://asset/{{item.assetID}}` **Fallback URL:** `https://apps.apple.com/app/myapp` *(or Google Play)* **Fallback Message:** `"This feature requires the MyApp mobile app."` Alternatively, combine with [Device Detection](/destinations/device-detection) to route iOS users to the App Store and Android users to Google Play. ## App Links vs Device Detection These two features are complementary, not alternatives: | Problem | Solution | | --------------------------------------------- | ---------------------------------------------------------- | | App not installed | Fallback URL (this page) | | Wrong browser on iOS (app links blocked) | [Device Detection routing](/destinations/device-detection) | | Different platforms need different app stores | [Device Detection routing](/destinations/device-detection) | For Mitti specifically: iOS Safari works with `iauditor://` deep links, but Chrome on iOS blocks them. If your team uses mixed browsers, consider combining both approaches — device routing to serve the web link on iOS Chrome, and fallback URL to catch anyone without the app installed on other devices. ## Related * [Mitti Integration](/integrations/mitti/setup) — full deep link and fallback setup for iAuditor * [Device Detection](/destinations/device-detection) — route users based on device, OS, and browser * [Conditional Visibility](/destinations/conditional-visibility) — show Destinations to specific audiences * [Pages Overview](/pages/pages-overview) — setting up multi-Destination Pages # Collection Fields Reference Source: https://help.qrtub.com/destinations/collection-fields The collection.* catalog — why the Collection binding prefix is still tub, which Collection values resolve, and the two metadata paths the editor offers that never populate The Collection namespace reads the Collection that the scanned Item belongs to — its name, its description, its cover image. Every Item in the Collection sees the same values, which is what makes these bindings useful for branding a URL or a Page and largely useless for identifying a specific Item. ## Available fields | Binding | Type | Notes | | ------------------------ | ------ | ---------------------------------------------------------------------------------------------- | | `collection.name` | string | The Collection's display name, for example `Heavy Equipment` | | `collection.description` | string | Free-text description; often empty | | `collection.image_url` | string | URL of the Collection's cover image | | `collection.items_name` | string | The custom label for this Collection's Items, for example `Machines`. Empty unless you set one | | `collection.id` | string | QRtub's internal identifier for the Collection — long and opaque | | `collection.created_at` | date | When the Collection was created, as an ISO timestamp | | `collection.updated_at` | date | When the Collection was last changed, as an ISO timestamp | There are no custom fields at Collection level. Custom fields are defined *by* a Collection and belong to its Items, so they are read as `item.*` — see [Item Fields Reference](/destinations/item-fields). ## `collection.metadata` is not a binding surface `collection.metadata` exists, but it holds QRtub's own configuration for the Collection — its field definitions, its Link generation rule, its scan-behavior defaults. Nothing in it is a stable, documented value to bind against, and its internal structure can change between releases. Two paths under it deserve a specific warning, because the editor's property picker offers them as if they were real data: * `collection.metadata.page.is_public` * `collection.metadata.organizationName` **Neither is ever populated.** No part of QRtub stores a value at either path, so both resolve to nothing. In a condition that means the whole expression evaluates to `false` and the rule never fires; in a Destination URL it means every binding in that URL counts as unresolved and the Destination is skipped. If you need to know whether a Page is private, check the Collection's privacy setting in the interface rather than trying to read it from a binding. ## When Collection fields are worth using The honest answer is: less often than Item fields. A `collection.*` value is identical for every Item in the Collection, so it cannot identify anything. The cases where it does earn its place are: * **Passing your own grouping to another system**, so a work-order URL arrives tagged with the Collection it came from: `https://cmms.example.com/wo/new?asset={{item.item_number}}&group={{collection.name}}`. * **Labeling a shared Page template** with `{{collection.name}}` so one template reads correctly across several Collections. Both are cosmetic. If the receiving system needs to distinguish one Item from another, bind an `item.*` field. And remember that values are inserted with no URL encoding, so a Collection name containing a space or an ampersand will break the URL it is inserted into — see [Field Bindings & URL Templates](/destinations/field-bindings). ## Related * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax, encoding and missing-value rules * [Item Fields Reference](/destinations/item-fields) — the `item.*` catalog, including custom fields * [What Is a Collection?](/collections/overview) — the entity these fields describe * [Page Privacy: Public vs. Private](/pages/page-privacy) — where the public/private setting actually lives # Conditional Destinations & Rule Priority Source: https://help.qrtub.com/destinations/conditional-destinations Route one QR code to different URLs with an ordered list of rules — first match wins, why a rule whose binding fails is skipped entirely, and where the catch-all sits. Conditional Destinations are an ordered list of rules on one Item, each pairing a condition with a URL. At scan time QRtub walks the list from the top; the first rule whose condition is true **and** whose URL fully resolves is where the visitor goes. If no rule produces a usable URL, the scan falls back to the Item's plain Default URL. This is a routing decision — which of several URLs a single code opens. It is not [Conditional Visibility](/destinations/conditional-visibility), which shows or hides one section on a Page. Routing rules decide the redirect itself, so they work even when there is no Page at all. ## Where you set the rules Open the Item, go to its **Destination** tab, and select **Destination Link**. Below the **Default URL** field is a checkbox labeled **Enable conditional routing**. Checking it reveals a **Routing Rules** list, badged **First match wins**. Each rule is a numbered card (Rule 1, Rule 2, …) with two fields: * **When** — a CEL condition, such as `item.status == "active"`. Leave it empty and the rule always matches. * **Then** — the URL to redirect to, which may contain `{{ }}` bindings. **Else** connectors show the order, and the chevron buttons move a card up or down. That order *is* the priority. The optional **Label** (the tag button) documents a rule for whoever edits it next; it has no effect on matching. The same editor appears on a Link not yet attached to an Item, in the Access Links area — there only `device.`, `time.`, `request.` and `link.` values exist, since an Item's fields are unavailable until the Link is assigned. ## The order a scan follows Rules are evaluated in list order, and evaluation stops at the first rule that yields a complete URL: 1. Evaluate the condition. No condition counts as a match. 2. Resolve every `{{binding}}` in that rule's URL. 3. If all of them resolved to a non-empty value, that URL wins and nothing below it is read. 4. Otherwise, continue to the next rule. 5. After the last rule, the Default URL is tried the same way. A rule with an empty condition matches everything, so every rule below it is unreachable — put the unconditional case in the Default URL instead. And since only the first match is used, overlapping conditions never both apply: order the most specific rule first. ```text theme={null} Rule 1 When item.type == "crane" Then https://forms.example.com/crane?asset={{item.assetID}} Rule 2 When "heavy-equipment" in item.tags Then https://forms.example.com/heavy?asset={{item.assetID}} Default https://forms.example.com/general?site={{collection.name}} ``` ## A rule whose URL does not fully resolve is skipped If any binding in a matched rule's URL fails to resolve, QRtub discards that rule and continues down the list rather than sending a half-built URL. This is the likeliest cause of a scan going somewhere unexpected: the rule matched, but its URL was never used. A binding fails when it resolves to nothing (an empty or missing field), or to a list or an object — `{{item.tags}}` holds several values and cannot go into a URL, so it counts as unresolved too. A URL resolving to only whitespace is discarded the same way. So a crane rule needing `{{item.assetID}}` silently hands over to the next rule for every crane with a blank asset ID. The Default URL behaves the same way: if its bindings do not all resolve, there is no usable Destination at all. Full binding syntax and every namespace are in [Field Bindings & URL Templates](/destinations/field-bindings). ## An impossible condition is false, not an error A condition that references something that does not exist evaluates to **false**, with no error anywhere. A typo (`item.stauts`), wrong capitalization (field names are case-sensitive), the wrong prefix (`collection.name`), or an invented value all produce a rule that never fires. There is no current-date value and no date arithmetic, so `today > item.dueDate` is not a broken rule — it is a rule that is permanently false. That means a rule that never matches and a rule that legitimately does not apply look identical from the outside. Leaving the **When** field runs a check that catches structural problems — over 500 characters, unbalanced parentheses or brackets, nesting deeper than 10, more than 20 operators — but nothing about whether the condition can ever be true. Pick fields from the editor's suggestions rather than typing them, and test against an Item you know should match. ## Reading the preview before you publish The editor evaluates rules live against the Item you are editing, your browser, and the current time. Each rule card shows a **Match** or **No Match** badge, and a **Preview** block shows the URL that would be used, labeled either `Matched rule 2: item.type == "crane"` or **Using default URL**. When a rule is skipped for an unresolved binding, the preview lists it under **Binding errors**, for example `Rule 1: Skipped - unresolved: item.assetID`. That list numbers rules from zero while the cards are numbered from one, so `Rule 1` in an error message is the card labeled **Rule 2**. A condition that never matches produces no entry in that list at all — it is only ever a **No Match** badge. What the preview cannot tell you: device and location conditions are evaluated against *your* device, and time conditions against the moment you look. All `time.*` values are UTC. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) — the full resolution order, and what a visitor sees when nothing resolves * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax and every namespace a rule can read * [Conditional Visibility](/destinations/conditional-visibility) — the other CEL mechanism: showing or hiding a section on a Page * [App Links & Fallback URLs](/destinations/app-links) — each rule can carry its own web fallback for a deep link # Conditional Visibility Source: https://help.qrtub.com/destinations/conditional-visibility Show or hide one section on a Page with a CEL condition — including why a typo silently hides the section instead of raising an error. Conditional Visibility decides whether a single section on a Page renders at all. You write one CEL expression on the section; it is evaluated at scan time against that Item, that visitor's device, and the current time. True renders the section, false leaves it out entirely. This is a show/hide decision about one thing on a Page. It is not how you choose between two URLs — that is a different mechanism — the [Destination's own conditional routing rules](/destinations/conditional-destinations) — and it works even when there is no Page at all. ## Where the condition lives In the Page Editor, select a section, then open the **Visibility** group in the Properties panel on the right. The field is labeled **Show When (CEL Expression)**. Any section type can carry a condition — not just Destination buttons. A Text block, a Banner, a whole Container (which hides its children with it), an ImageSection: all of them accept one. Leaving the field empty means the section is always visible. As you type, a **Preview** badge next to the field reads **Visible** or **Hidden**, evaluated against whichever Item you have selected in the editor. Switch the previewed Item to check the condition against real data instead of your base template. ## What a condition can look at Everything the Page itself can bind to is available in a condition: | Namespace | Holds | | -------------- | -------------------------------------------------------------------- | | `item.*` | This Item's fields, standard and custom | | `collection.*` | The Collection's name, description, and metadata | | `device.*` | Device type, OS, and browser of the person scanning | | `time.*` | Hour, day of week, day of month, month, year, weekend flag — all UTC | | `request.*` | Path, referrer, language, and CDN-derived country and city | | `session.*` | The signed-in viewer, when there is one — null for anonymous scans | | `theme.*` | The Page's accent color and radius | ## Working examples Show a section only for one equipment type: ```text theme={null} item.type == "forklift" ``` Show a section only for Items carrying a tag: ```text theme={null} "heavy-equipment" in item.tags ``` Show a warning banner only when a status field says so: ```text theme={null} item.testStatus == "expired" ``` Combine conditions with `&&`, `||`, and `!`, and group with parentheses: ```text theme={null} ("crane" in item.tags || "heavy-equipment" in item.tags) && item.status == "active" ``` Restrict a section to one Collection when the Page template is shared: ```text theme={null} collection.name == "Sydney Depot" ``` ## A wrong condition and an unmet condition look identical If a condition references something that does not exist, the whole expression evaluates to **false** — silently. The visitor sees no error; the section simply is not there. Even in the editor, the Preview badge reads **Hidden** rather than **Error**, because a failed lookup is treated as a false result rather than as a failure. That makes these three situations indistinguishable at a glance: * A genuine miss — this Item really is not a forklift. * A typo — `item.tpye == "forklift"`, or a field name whose capitalization does not match (field names are case-sensitive). * An invented value — `today > item.dueDate`. There is no `today`. **`time` exposes only the parts listed above — no absolute date and no date arithmetic**, so "show this when the inspection is overdue" cannot be expressed. Use a status field you maintain (`item.testStatus == "expired"`) instead of comparing dates. The practical defense is to build conditions by picking fields from the editor's suggestions rather than typing them, and to verify against a real Item that you know should match before installing. ## Expression limits Every condition is validated before it is evaluated, and a condition that breaks a limit is rejected in the editor rather than silently ignored: * Maximum 500 characters * Maximum nesting depth of 10 for brackets and parentheses * Maximum 20 operators * Parentheses and brackets must balance If you are anywhere near these ceilings, the logic almost certainly belongs in a field on the Item rather than in an expression on the Page. ## Before you add a condition Ask whether showing everything is simpler. A Page with four buttons where people tap the one they need is easier to build, easier to debug, and easier for a contractor to understand than four conditions. Conditional Visibility earns its place when the wrong button is actively harmful — a crane inspection form on a forklift, for example. Also note that an ActionLink already hides itself when its own URL binding cannot resolve, with no condition needed — see [ActionLink: The Destination Button](/pages/action-link). You do not need a condition to suppress a button that has nowhere to go. ## Related * [Conditional Destinations & Rule Priority](/destinations/conditional-destinations) — the other CEL mechanism: conditional routing rules choosing which URL a scan uses * [Device Detection & Routing](/destinations/device-detection) — the `device.*` fields you can test in a condition * [Section Types](/pages/section-types) — every section that can carry a condition * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax and full namespace reference # Device Detection & Routing Source: https://help.qrtub.com/destinations/device-detection The device, OS and browser fields a condition can read, what they are reliably good for, and where they are the wrong tool. QRtub reads the device from the User-Agent on every scan, so a condition can show one Destination on a phone and a different one on a desktop. These are conditions on the **device**, not on the person. Someone in the field on a laptop gets the desktop branch; someone at a desk on their phone gets the mobile one. If the distinction you need is about *who* is scanning, see [Conditional Visibility](/destinations/conditional-visibility) for what a condition can actually read. ## What you can read | Field | Values | Convenience flags | | ---------------- | -------------------------------------------------------------- | ---------------------------------------------------------- | | `device.type` | `mobile` · `tablet` · `desktop` | `device.isMobile` · `device.isTablet` · `device.isDesktop` | | `device.os` | `ios` · `android` · `windows` · `macos` · `linux` · `unknown` | `device.isIOS` · `device.isAndroid` | | `device.browser` | `chrome` · `safari` · `firefox` · `edge` · `opera` · `unknown` | — | ``` device.isMobile device.os == "ios" device.browser == "chrome" || device.browser == "edge" ``` **When the device cannot be detected**, QRtub assumes `desktop`, `unknown`, `unknown`. So a desktop-conditioned Destination is what an unrecognised device falls into — worth knowing when you choose which branch carries the fallback. ## The two cases worth using it for **The right app store.** One Destination at `apps.apple.com/...` with `device.isIOS`, another at `play.google.com/...` with `device.isAndroid`. **iOS deep links outside Safari.** An app scheme like `iauditor://` only opens from Safari on iOS, so an iPhone user in Chrome needs the web URL instead: ``` device.isIOS && device.browser != "safari" → the web Destination device.isDesktop || !device.isIOS || (device.isIOS && device.browser == "safari") → the app Destination ``` This is narrower than it looks. If your worry is just *"what if the app is not installed?"*, that is already handled — see [App Links & Fallback URLs](/destinations/app-links), no device condition needed. Device routing is for the case where the app *is* installed but the browser blocks the scheme. ## Combining with Item data Device conditions and Item fields go in the same expression: ``` device.isMobile && item.type == "crane" ``` ## Where it is the wrong tool * **Never for access control.** User-Agent is self-reported, users can change it, and privacy browsers mask it. Use authentication. * **Not to force a choice.** If showing both options is simpler, show both. * **Not as a stand-in for identity.** See the note at the top. **Always leave one Destination with no device condition**, so an unrecognised device still has somewhere to go. ## Related * [App Links & Fallback URLs](/destinations/app-links) * [Conditional Visibility](/destinations/conditional-visibility) * [Field Bindings & URL Templates](/destinations/field-bindings) # Field Bindings & URL Templates Source: https://help.qrtub.com/destinations/field-bindings The double-curly-brace syntax for inserting live data into a Destination URL, the eight namespaces you can read from, and the encoding and missing-value rules A field binding is a placeholder you write inside a Destination URL that QRtub replaces with real data at the moment someone scans. It is what lets one URL template serve every Item in a Collection instead of one URL per Item. ```text theme={null} https://app.example.com/inspection/new?assetId={{item.serial_number}} ``` Scan the code on Item "EXC-203", whose serial number is `SN-2024-203`, and the browser opens: ```text theme={null} https://app.example.com/inspection/new?assetId=SN-2024-203 ``` The same template on a different Item substitutes that Item's serial number, so every code routes to its own pre-filled URL from one configuration. ## Syntax rules Write a namespace, a dot, and a field name, wrapped in **double** curly braces. * **Double braces are required.** `{item.name}` is not a binding. Single braces are sent to the browser literally, so the receiving system gets the characters `{item.name}` instead of a value. * **The namespace prefix is required.** `{{name}}` does not resolve; write `{{item.name}}`. * **Field names are case-sensitive.** `{{item.Status}}` does not resolve. `{{item.status}}` does. * **Spaces inside the braces are ignored.** `{{ item.name }}` behaves identically to `{{item.name}}`. * **You can use as many bindings as you like in one URL**, mixed freely with literal text: `https://cmms.example.com/wo/new?asset={{item.item_number}}&site={{item.location}}`. The same field names go into a condition without the braces — `item.status == "operational"`. Braces build a value; a bare reference tests one. ## The namespaces Eight namespaces exist. Each one is only readable where the data behind it exists, which is why the last three are not available everywhere. | Namespace | What it holds | Available in | | ------------ | ------------------------------------------------------------------------------------------------------------- | ---------------------- | | `item` | The scanned Item's own fields, standard and custom — see [Item Fields Reference](/destinations/item-fields) | Destinations and Pages | | `collection` | The Collection the Item belongs to — see [Collection Fields Reference](/destinations/collection-fields) | Destinations and Pages | | `device` | The scanning device's type, OS and browser — see [Device Detection & Routing](/destinations/device-detection) | Destinations and Pages | | `time` | The current hour, day, month and year in UTC — see [Time Fields Reference](/destinations/time-fields) | Destinations and Pages | | `request` | Language, referrer and CDN-derived location — see [Request Fields Reference](/destinations/request-fields) | Destinations and Pages | | `link` | The specific Link that was scanned: its slug, strategy and sequence number | Destinations only | | `session` | The signed-in team member viewing the Page, if any | Pages only | | `theme` | The Page's accent color and border radius — see [Theming a Page](/pages/page-theming) | Pages only | ## Values are inserted exactly as stored There is **no automatic URL encoding**. Whatever is in the field is dropped into the URL character for character. A field value containing a space, an ampersand, a question mark or a slash will produce a URL that the receiving system reads differently from what you intended — an `&` in a value, for example, looks to the receiving system like the start of a new query parameter. Either confirm the receiving system tolerates those characters, or keep bound fields to plain identifiers — serial numbers, asset numbers, Item IDs — which is what most templates use anyway. ## What happens when a field is empty This differs depending on where the binding sits, and the difference matters. **In a Destination URL, an empty or missing field invalidates the whole URL.** QRtub will not open a half-built link. If any binding in the template resolves to nothing, that Destination is treated as unresolved: a conditional rule is skipped and the next rule is tried, and a plain Destination URL resolves to nothing at all, which lands the scan on the "this link isn't ready yet" screen instead of a broken URL. The same rule applies to a binding that resolves to a list or a nested object rather than a single value — `{{item.tags}}` is an array, so a URL containing it never resolves. **In a Page section, an empty field renders as an empty string** and most sections then hide themselves rather than display a blank. The exception is the ActionLink section, which checks its own `href` first and hides itself entirely if a binding there cannot be resolved. Neither case produces an error message. A Destination that quietly never fires is almost always a binding that never resolved, so check the field name's spelling and case first, and then check that the Item you are testing with actually has a value in that field. ## Session fields `session` describes the signed-in team member looking at a Page, and is empty for an ordinary anonymous scan. There are two usable values, `session.user.id` and `session.user.email`, plus the `session.user` object itself, which is what the common test uses: ```text theme={null} session.user != null ``` That expression is true only for a signed-in member of your team, which is how the AdminToolbar section keeps owner-only shortcuts off the version of the Page the public sees. `session` is not part of the data available when a Direct-Mode scan resolves a Destination, so it cannot be used to route a redirect. ## Renaming a field does not break a binding If you rename a custom field on a Collection, QRtub rewrites the Destination URLs, fallback URLs and conditions that referenced the old name, in place, when you save. Page template bindings are stored against a hidden stable identifier and never see the rename at all. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) — where a scan is routed, and the order QRtub checks * [Item Fields Reference](/destinations/item-fields) — the full `item.*` catalog, including custom fields * [Renaming a Field](/fields/renaming-a-field) — why a rename is safe and what it updates # Item Fields Reference Source: https://help.qrtub.com/destinations/item-fields Every item.* binding: the four core fields, the standard fields a new Collection ships with, the read-only system fields, and your own custom fields The `item` namespace reads the scanned Item's own data, and it is the namespace you will use for almost everything. Write it as `{{item.field_name}}` in a Destination URL, or as `item.field_name` without braces in a condition. See [Field Bindings & URL Templates](/destinations/field-bindings) for the syntax rules and the encoding behavior. The exact set of `item.*` fields depends on the Collection, because a Collection defines its own fields. The tables below cover what every Collection has plus what a new one starts with. ## Core fields Four fields exist on every Item in every Collection, are stored in their own database columns, and cannot be renamed or removed. | Binding | Type | Notes | | ------------------ | ------ | ------------------------------------------------------------------------------------------------------------ | | `item.name` | string | The Item's display name, for example `Excavator #203` | | `item.item_id` | string | The Item ID — your own identifier, unique within the Collection, and the value ID-based Links are built from | | `item.description` | string | Free-text description | | `item.tags` | array | The tags list, for example `["construction", "rental"]` | ## Standard fields A new Collection ships with these fields defined. They are ordinary configurable fields, not fixed columns: you can relabel, rename, disable or delete them, and the last four are switched **off** by default, so they resolve to nothing until you enable them on the Collection. | Binding | Type | On by default | | ------------------------ | ------ | ------------- | | `item.item_number` | string | Yes | | `item.serial_number` | string | Yes | | `item.category` | string | Yes | | `item.type` | string | Yes | | `item.subtype` | string | Yes | | `item.status` | string | Yes | | `item.location` | string | Yes | | `item.owner` | string | Yes | | `item.equipment_manager` | string | No | | `item.notes` | string | No | | `item.manufactured_date` | date | No | | `item.parent_item` | string | No | **`item.item_number` and `item.item_id` are different fields.** Item Number is the standard SKU-style field above; Item ID is the core identifier that Links can be generated from. There is no `item.number`. ## System fields These are set by QRtub, not by you, and are read-only. | Binding | Type | Notes | | ----------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------- | | `item.id` | string | QRtub's internal identifier for the Item — long and opaque; prefer `item.item_id` or `item.item_number` in a URL you have to read or support | | `item.created_at` | date | When the Item was created, as an ISO timestamp | | `item.updated_at` | date | When the Item was last changed, as an ISO timestamp | | `item.image` | string | URL of the Item's image | ## Custom fields Any field you add to a Collection is readable under its field key, with no extra prefix. A field you created with the label "Inspection Due" and the key `inspection_due` is `{{item.inspection_due}}` in a URL and `item.inspection_due` in a condition. Field keys are lowercase letters, numbers and underscores, so a binding for a custom field is always lowercase. If you are unsure of a key, open the Collection's **Fields** tab — the key is shown next to the label. Renaming a custom field does not break existing bindings. QRtub rewrites the Destination URLs, fallback URLs and conditions that used the old key when you save the rename, and Page template bindings are stored against a hidden stable identifier that a rename never touches. ## Things that catch people out **Field names are case-sensitive.** `item.Status` resolves to nothing. `item.status` works. **Tags cannot go in a URL.** `item.tags` is a list, not a single value, and a binding that resolves to a list makes the whole URL count as unresolved — the Destination is skipped rather than opening with `construction,rental` pasted into it. Tags work normally in conditions, where you test them with `in` and `size()`: ```text theme={null} "crane" in item.tags size(item.tags) > 0 ``` **A disabled field disappears from a Page.** When a Page renders, QRtub passes only the Collection's enabled fields into the data a binding can read, so turning a field off on the Collection makes `{{item.that_field}}` resolve to nothing on every Page that used it. **Dates are text, not numbers.** `item.created_at`, `item.manufactured_date` and any date custom field come through as ISO-style strings. You can insert them into a URL, but you cannot do arithmetic on them or compare them against today's date — see [Time Fields Reference](/destinations/time-fields) for why, and what to do instead. ## Related * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax, encoding and missing-value rules * [Core Fields vs. Custom Fields](/fields/core-vs-custom) — which fields are fixed and which you control * [Collection Fields Reference](/destinations/collection-fields) — the `collection.*` catalog for Collection-level data * [What Is a Destination?](/destinations/what-is-a-destination) — conditional routing rules that send different Items to different URLs # Request Fields Reference Source: https://help.qrtub.com/destinations/request-fields The request.* values — language, referrer, timestamp and CDN-derived country, city and IP — where each comes from, when each is empty, and what binding them discloses The `request` namespace describes the incoming scan itself rather than the Item behind it: what language the browser asked for, where the visitor came from, and roughly where in the world they are. The location values are not measured by QRtub — they are read from headers the content delivery network adds in front of the app, which is why they are approximate and why several of them are frequently empty. ## Available fields | Binding | Type | Source | Empty when | | ------------------- | ------ | ------------------------------------------------------------------------------ | ---------------------------------------- | | `request.timestamp` | string | The moment the request was handled, as an ISO timestamp in UTC | Never | | `request.path` | string | The path that was requested | Never | | `request.language` | string | The first entry of the browser's `Accept-Language` header, for example `en-US` | The browser sends no language preference | | `request.referrer` | string | The `Referer` header — the page the visitor came from | A direct QR scan, which is most of them | | `request.country` | string | Two-letter country code from the CDN's geo header, for example `AU` | The CDN did not supply one | | `request.city` | string | City name from the CDN's geo header, for example `Brisbane` | The CDN did not supply one | | `request.ip` | string | The client IP address, taken from the forwarded-for headers | No forwarded address is present | Two behaviors surprise people: * **`request.referrer` is usually empty.** A phone camera opening a QR code sends no referrer, so a rule built on it will not fire for the scans you actually care about. * **`request.path` is always `/` when a Page renders.** It carries the real requested path during Destination routing, but the Page renderer does not pass the path through. ## Location values are not available in preview `request.country`, `request.city` and `request.ip` come from headers the CDN adds to a real inbound request. When you preview a Page or test a Destination inside the editor, the context is built in your own browser instead, and those three are always empty. There is no way to fake them in preview, so a location-based rule can only be verified with a real scan. Combined with the missing-value rule, that has teeth: **a Destination URL containing `{{request.city}}` resolves to nothing whenever the header is absent, and QRtub skips that Destination rather than opening a half-built URL.** If you route on location, always pair the rule with an unconditional fallback so a visitor the CDN could not place still lands somewhere. And because bindings are inserted with no URL encoding, a city name containing a space will break the URL it is inserted into. ## What binding this data discloses State this to yourself plainly before you use it: **the moment you put `{{request.ip}}`, `{{request.country}}` or `{{request.city}}` into a Destination URL, you are sending that data to whoever runs the system on the other end.** It arrives in their query string, and from there it lands in their server logs, their analytics and any third-party script on the page they open — permanently, and outside your control. The person scanning gets no notice and no choice. They pointed a camera at a sticker; they did not agree to have their approximate location forwarded to a vendor. An IP address is personal data under the GDPR and comparable regimes, and city-level location is widely treated the same way, so if you operate anywhere those rules apply, forwarding it is a decision to make deliberately rather than a convenient parameter to add. Two practical guardrails: * **Prefer `request.country` over `request.city` or `request.ip`.** A country code is usually all a routing decision needs, and it discloses the least. * **Use these values in conditions rather than in URLs where you can.** Routing an Australian scanner to your Australian support page keeps the data inside QRtub; putting the city in the URL hands it to someone else. Location data derived from an IP address is also inaccurate often enough to matter — VPNs, corporate networks and mobile carriers routinely resolve to the wrong city or the wrong country. Like device detection, this is a routing convenience, not a security control: never use `request.*` to decide who may see something. ## Related * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax, encoding and missing-value rules * [What Is a Destination?](/destinations/what-is-a-destination) — resolution order, and the conditional routing rules that read these fields * [Device Detection & Routing](/destinations/device-detection) — the other scan-time namespace, and the same "not for security" caveat * [Time Fields Reference](/destinations/time-fields) — the other values computed fresh at every scan # Time Fields Reference Source: https://help.qrtub.com/destinations/time-fields The time.* values — hour, dayOfWeek, dayOfMonth, month, year, isWeekend — computed in UTC at every scan, and why they cannot express whether something is overdue The `time` namespace exposes the current moment as a handful of separate numbers, so a Destination can behave differently during business hours or at the weekend. It is always available, in both Destination routing and Page rendering, and it is recomputed every single time a code is scanned — there is nothing to refresh or schedule. ## Available fields | Binding | Type | Range | Notes | | ----------------- | ------- | ----- | ----------------------------------- | | `time.hour` | number | 0–23 | Hour of day | | `time.dayOfWeek` | number | 0–6 | 0 is Sunday, 6 is Saturday | | `time.dayOfMonth` | number | 1–31 | Day of the month | | `time.month` | number | 1–12 | 1 is January | | `time.year` | number | — | Four-digit year, for example `2026` | | `time.isWeekend` | boolean | — | `true` on Saturday and Sunday | **Every value is UTC.** There is no timezone setting, and QRtub does not adjust for the scanner's location or your account's country. Typical conditions: ```text theme={null} time.hour >= 9 && time.hour < 17 time.isWeekend == true time.dayOfWeek == 1 ``` These are conditions, not URL material. The values are plain numbers, so `{{time.year}}` will insert `2026` into a URL if you need it, but the reason `time` exists is to decide *which* Destination fires — an after-hours emergency number instead of the daytime service desk, for example. ## Working around UTC Because the values are UTC, a "business hours" rule written as `time.hour >= 9 && time.hour < 17` describes 9am to 5pm in London in winter, not in your city. Convert your local hours to UTC and write those numbers instead. For a site on UTC+10, 9am local is `23` and 5pm local is `7`, so the window wraps past midnight and has to be written as two ranges joined with `||` rather than one. The same wrap affects `dayOfWeek` and `isWeekend`: for anywhere far enough east or west, the UTC day rolls over part-way through the local working day, so a weekday rule can misfire in the early morning or late evening. If exact local-time accuracy matters, treat `time` as a rough convenience rather than a scheduling engine. ## Why you can't check if something is overdue **You cannot.** This is the most common thing people try to build with `time`, and it is not possible today. `time` exposes only the parts listed above. There is no full date value — no `time.today`, no `time.date`, no `time.now` — and there is no date arithmetic, no way to subtract one date from another, and no way to compare a stored date field against the current date. A condition like `item.inspection_due < time.today` refers to something that does not exist. It also fails quietly. An undefined identifier makes the entire condition evaluate to `false`, with no error raised at scan time — so the rule simply never fires, and the Destination you attached it to never appears. Nothing in the scan itself tells you the expression was invalid rather than merely unmatched. **Do this instead: keep a status field that you maintain.** Add a field to the Collection such as `inspection_status` with allowed values like `current` and `expired`, and write the condition against that: ```text theme={null} item.inspection_status == "expired" ``` Whatever already tells you an inspection has lapsed — your inspection software, a spreadsheet, a scheduled review — is what sets that field, in bulk via CSV import or one Item at a time. QRtub then routes on a value it can actually read. It is a small amount of upkeep in exchange for a rule that works. ## Related * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax and the namespaces available * [What Is a Destination?](/destinations/what-is-a-destination) — where time-based conditional routing rules are ordered * [Conditional Visibility](/destinations/conditional-visibility) — hiding a section with a condition, and other silent-`false` causes * [Allowed Values](/fields/allowed-values) — setting up the status field this page recommends # What Is a Destination? Source: https://help.qrtub.com/destinations/what-is-a-destination Where a scan is routed, the exact order QRtub checks when someone scans a code, and what a visitor sees when nothing resolves. A Destination is where a scan ends up. It is a URL that QRtub either redirects to immediately or shows as a button on a Page — an inspection form, a maintenance system, a PDF manual, a phone number, a mobile app deep link. The QR code itself never contains the Destination. It contains a Link, and the Link resolves to a Destination at the moment of the scan. That indirection is the whole point: you can change where a code goes without reprinting anything. ## Where Destinations are set Destinations are set on the Item, on the Item's Destination tab: * **Default URL** — the single Destination a Direct-Mode scan redirects to. This is the plain, unconditional URL. * **Conditional routing rules** — an ordered list that can pick a different URL per scan based on the Item's data, the device, or the time. If the Item's Link opens a Page instead, each Destination is a button on that Page — an ActionLink, Button, or Link section with its own URL. One Item can carry as many of those as you need. Which of the two behaviors you get is the Direct Mode / Page Mode choice, covered in [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode). ## The resolution order for a scan For a scan that redirects (rather than opening a Page), QRtub checks **only that Item's own destination data**, in this order: 1. **Conditional routing rules**, if the Item has any enabled. Rules are evaluated top to bottom and the first match wins — see [Conditional Destinations & Rule Priority](/destinations/conditional-destinations). 2. **The Item's Default URL**, with any `{{bindings}}` resolved. 3. **Nothing.** If neither produces a usable URL, the visitor gets the "not ready yet" page below. Two consequences catch people out: **A URL whose bindings do not all resolve counts as no URL at all.** If your Default URL is `https://cmms.example.com/asset/{{item.equipmentID}}` and this Item's `equipmentID` is empty, QRtub does not send a half-built URL — it skips that URL and moves to the next step in the order. The same applies per rule. **The Collection's default destination pattern is not consulted at scan time.** That pattern is stamped onto each Item when the Item is created and then belongs to the Item. Editing the pattern later changes nothing about Items that already exist. See [Default Destination for New Items](/collections/default-destination). Note that an Item carrying enabled conditional rules always routes, even when its Collection is set to Page Mode — the rules take precedence over showing a Page. If the rules then match nothing and there is no Default URL, the Page is shown after all. ## Values go into a URL exactly as stored A Destination can pull Item data into the URL with double-brace bindings, so one template serves every Item in a Collection: ```text theme={null} https://app.example.com/inspect?id={{item.serial_number}}&site={{collection.name}} ``` **There is no automatic URL encoding.** The stored value is inserted character for character. A field containing a space, an `&`, or a `?` will break the link. Keep values that feed a URL simple, or use a field that holds an ID rather than a description. Full syntax and the available namespaces are in [Field Bindings & URL Templates](/destinations/field-bindings). ## "This access link isn't ready yet" When a scan resolves to an Item that is explicitly set to **Destination Link** but has no usable Destination, QRtub shows a plain page headed "This access link isn't ready yet". It displays the Link's own public URL and nothing else — never an internal Item, Collection, or team ID — plus an **Open in QRtub** button. Who sees what: * **Anonymous visitors** see the not-ready page. It tells them the code is assigned but has no destination yet, and that the owner may still be configuring it. * **Signed-in members of the owning team** are sent instead to the authenticated view for that Link, where the Destination can be set. Membership is checked on the server before anything is revealed. An Item that was never explicitly set to Destination Link does not show this page — it falls through to its Page instead. So a blank-looking Page and a not-ready page are two different symptoms: the first means no Destination buttons resolved, the second means the Item is meant to redirect and has nowhere to send anyone. ## A code changes where people go, not what they can see QRtub keeps no copy of another system's data and makes no API connection to it. It stores the address and nothing else, so **every Destination keeps its own permissions exactly as they are**. Putting a code on something grants nobody anything they did not already have. Someone who scans a Link to a restricted document meets that system's sign-in, because protecting it is that system's job and it is still doing it. That makes a tag for a mixed audience a design decision — publish what the public should have on a [Page](/pages/pages-overview) and list the internal Destinations alongside it — rather than a risk. ## Unsafe URLs are refused QRtub blocks script-executing URL schemes — `javascript:`, `data:`, and `vbscript:` — wherever a Destination is used. Whitespace and control characters are stripped before the check, so tricks like `java\tscript:` are caught too. What you see if one is stored: on a Page, the button renders with a dead `#` link; on a direct scan, the request returns a 404 rather than executing anything. A fallback URL using one of these schemes is discarded the same way. Ordinary app schemes such as `tel:`, `mailto:`, and `myapp://` are unaffected — those are [app links](/destinations/app-links) and are handled deliberately. ## Related * [App Links & Fallback URLs](/destinations/app-links) — deep links, and what happens when the app isn't installed * [Field Bindings & URL Templates](/destinations/field-bindings) — the `{{ }}` syntax and every available namespace * [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode) — redirect straight to one Destination, or open a Page of them # Allow New Values Source: https://help.qrtub.com/fields/allow-new-values The per-field toggle deciding whether a value outside the Allowed Values list can be typed in or imported — and why it switches off allowed-values checking on CSV import entirely. **Allow New Values** decides whether people are limited to the options on a field's [Allowed Values](/fields/allowed-values) list, or can add one that is not there yet. It is a checkbox on the field itself, in the Collection's **Fields** tab. The checkbox only applies to **List** fields. On any other type it stays disabled, and the editor tells you why: switch the Field Type to List first. Tags, the core list field on every Item, ships with Allow New Values already on, which is why you can type any tag you like without configuring anything. ## With it off The list is the whole vocabulary: * The Item form offers the list and nothing else. * A CSV import checks every cell in that column against the list and **rejects any row with a value that is not on it**, naming the offending value and listing what is allowed. Other rows in the file still import. This is the setting to keep for anything you filter, route, or condition on. A status column with three real values stays three values. ## With it on * In the Item form, the picker gains an "Add" box. Type a value, choose a color, and it is added to the Collection's Allowed Values list immediately — that one action saves straight away, unlike the rest of the Fields tab, which waits for **Save changes**. From then on the value is a normal option for every Item in the Collection, colored chip included. * Like values added in settings, a value typed here is stored lowercased with spaces turned into underscores, while the text you typed is kept as its label. ## The CSV interaction to know about **When Allow New Values is on, CSV import skips the allowed-values check on that field completely.** It is not a lenient check — there is no check. Any string in that column is accepted, and the row imports without a warning. That has a consequence worth stating plainly: `oprational` imports as happily as `operational`. And unlike a value typed into the Item form, a value that arrives by CSV is **not** added to the Allowed Values list. So it sits on the Item, out of the picker, with no chip color, and any condition testing for the correct spelling quietly fails to match it. If you rely on CSV import to keep a field clean, leave Allow New Values off and let the import reject the bad rows — the rejection report tells you exactly which rows and which values, and the good rows still land. Turn it on when the field is a genuinely open vocabulary that you want people to grow as they go. ## Related * [Allowed Values](/fields/allowed-values) * [Custom Field Types](/fields/field-types) * [Importing Items from CSV](/import-export/importing-items) * [Keywords](/items/keywords) # Allowed Values Source: https://help.qrtub.com/fields/allowed-values The fixed list of value, label and color options authored on a Text or List field, which turns it into a picker and colors the matching chip everywhere the field is shown. Allowed Values is a fixed list of literal values you author on the field itself. Give a field a list and it stops being a free-text box and becomes a picker, with each option carrying its own color. The values belong to this field — a field that instead points at another record and shows *that* record's data is a [Reference field](/fields/reference-fields), which never uses an allowed-values list. Allowed Values is available on **Text** and **List** fields only. On any other type the field editor says so and offers no list. ## Adding values to a field 1. Open the Collection's settings and go to the **Fields** tab. 2. Click the chip for the field you want, then **Manage Allowed Values**. 3. Type the option's text under **Add Value**, pick a color, and press **Add**. A preview chip shows what it will look like. 4. Press **Save changes** on the settings form. Until you do, the list is not saved. Each option is stored as three things: * **Value** — what is actually written onto the Item. Generated from what you typed, lowercased with spaces turned into underscores: "In Repair" becomes `in_repair`. * **Label** — what people see in the picker and on the Item. This keeps your capitals and spacing: "In Repair". * **Color** — the color of the chip for that option. Because the value is the part that gets stored, it is also the part you write in conditions and URL templates: `item.status == "in_repair"`, not `"In Repair"`. ## Colors are configured once and apply everywhere The color on each option is not just decoration in the picker. It is the color of that value's chip wherever the field is rendered: * in the Items table, * on the scanned Page, for Tags and for a Banner section bound to that field. So a status of `overdue` set to red shows red in your Items table and red on the page a customer scans, without configuring it twice. The match is on the stored value, exactly. If an Item holds a value that is not on the list — usually because it was imported, or typed in while [Allow New Values](/fields/allow-new-values) was on — it still displays, but with no color, because there is no option to take a color from. ## Changing or removing an option Editing the list changes the list, not the Items. Removing an option leaves any Item that already holds that value untouched: the value stays on the Item, but it is no longer offered in the picker and no longer has a color. Changing an option's color reaches every Item at once, since the color was never stored on the Item in the first place. There is no rename for an option's stored value. Adding a replacement and removing the old one leaves existing Items holding the old value, so re-pick those Items or re-import them. ## How strict is the list? By default, strict: the picker offers only what is on the list, and a CSV import rejects any row with a value that is not on it. That strictness is controlled by a single per-field toggle, and switching it on changes both the form and the import — see [Allow New Values](/fields/allow-new-values). ## Related * [Allow New Values](/fields/allow-new-values) * [Reference Fields](/fields/reference-fields) * [Custom Field Types](/fields/field-types) * [Keywords](/items/keywords) # Core Fields vs. Custom Fields Source: https://help.qrtub.com/fields/core-vs-custom The four fixed core fields every Item ships with, versus the custom fields you add — where each is stored, and why only custom fields can be renamed or deleted. Every Item in a Collection carries four core fields, plus any custom fields you add to that Collection. The difference is not cosmetic: core fields and custom fields are stored differently, and that decides what you are allowed to change later. ## The four core fields Every Collection has these four, always, and they cannot be removed: | Field | Key | Type | | ----------- | ------------- | ---- | | Name | `name` | Text | | Item ID | `item_id` | Text | | Description | `description` | Text | | Tags | `tags` | List | Each one has its own dedicated column in the database, which is why their keys are fixed forever. In the Fields tab, a core field's label and key are both locked — you can mark it required, and you can disable it to hide it from forms and tables, but you can never rename or delete it. ## Everything else is a custom field A custom field's values live together in one metadata block on the Item, keyed by a stable 8-character ID that QRtub generates when the field is created — something like `Xk9mPq7z`. You never see that ID. What you see and type is the field's key, such as `serial_number`, and the key is only a pointer to the ID. That indirection is the entire reason renaming a custom field is safe: the label and key change, the storage ID does not, so no data has to move. See [Renaming a Field](/fields/renaming-a-field) for what else follows the rename automatically. ## What the split actually changes | | Core field | Custom field | | ---------------- | ----------------------------- | -------------------------------------- | | Change the key | Never | Any time | | Change the label | Locked | Any time (the key follows it) | | Remove it | Disable only — data untouched | Delete permanently | | Stored as | Its own database column | A stable ID inside the Item's metadata | | Present in | Every Collection, always | Only the Collections you add it to | ## Where fields are configured Open the Collection, go to its settings, and choose the **Fields** tab. Fields appear as a row of chips under **Item fields**: click a chip to edit that field, drag it to reorder, and use the icon on the chip to disable a core field or delete a custom one. Nothing on this tab takes effect until you press **Save changes**. That includes adding a field, renaming one, editing its allowed values, and deleting one. One thing worth being clear about: a field's *definition* belongs to the Collection, while the *value* belongs to the Item. Add a field and it appears on every Item in that Collection at once, empty until someone fills it in. Delete it and it disappears from all of them. ## Related * [Creating a Custom Field](/fields/creating-a-field) * [Custom Field Types](/fields/field-types) * [Deleting and Disabling Fields](/fields/deleting-and-disabling) * [What Is a Collection?](/collections/overview) # Creating a Custom Field Source: https://help.qrtub.com/fields/creating-a-field Adding a field to a Collection: the display label, the auto-generated field key and its validation rules, the type, and the ready-made fields you can add instead. Custom fields are added in the Collection's settings, on the **Fields** tab. A new field appears on every Item in that Collection immediately, empty until someone fills it in. ## Adding a field 1. Open the Collection, go to its settings, and choose the **Fields** tab. 2. Click **Create Custom Field**. 3. Type a **Display Label** — the wording people see on forms and tables, e.g. "Warranty End Date". 4. Check the **Field Key** underneath. It is generated from your label (`warranty_end_date`) and you can edit it. It is validated as you type, and the form shows you the binding it produces: `{{ item.warranty_end_date }}`. 5. Choose a **Field Type**. See [Custom Field Types](/fields/field-types) for what each one gates. 6. Set the options you need — Required, and for a List field Multiple Values and Allow New Values. If the type is Text or List you can author its [Allowed Values](/fields/allowed-values) here too; if it is UUID you can set up its [reference configuration](/fields/reference-fields). 7. Click **Create Field**, then **Save changes** on the settings form. The field is not stored until you save. Behind the scenes the field is given a stable internal ID at this point, which is what lets you rename it later without touching any data. ## Field key rules The key is what you write in bindings and conditions, so it is deliberately strict: * lowercase letters, numbers, and underscores only, * between 2 and 64 characters, * no leading, trailing, or repeated underscores, * not a core field name (`name`, `item_id`, `description`, `tags`), * not a name QRtub uses internally (`id`, `created_at`, `updated_at`, `image`, `destination_url` and similar), * not a programming keyword such as `class`, `function`, or `return`, * unique within the Collection. Whatever the rule, the form tells you which one you broke and suggests a way out — a suffix like `status_2`, for instance. Because the label auto-generates the key, most of the time you never type one. ## Adding a ready-made field instead Under **Add More Fields**, QRtub offers a library of common fields — Item Number, Serial Number, Category, Type, Subtype, Status, Location, Owner, Equipment Manager, Notes, Manufactured Date, Parent Item. Clicking one adds it with a sensible type already set (Owner and Equipment Manager arrive as team-member references, Parent Item as an Item reference), and you can then click its chip and change anything you like. The same section lists any field on this Collection that is currently switched off, so it doubles as the way to bring a disabled field back. ## Ordering fields Fields show as chips in the order they are used on forms, tables, and CSV exports. Drag a chip to reorder, then **Save changes**. New fields land at the end. ## Reset to Defaults **Reset to Defaults** strips the Collection back to the four core fields, removing every custom field from the configuration. It does not ask for confirmation. Nothing is written until you press **Save changes**, so leaving the settings form without saving undoes it — but save, and the fields are gone under the same terms as [deleting one](/fields/deleting-and-disabling). ## Related * [Custom Field Types](/fields/field-types) * [Renaming a Field](/fields/renaming-a-field) * [Deleting and Disabling Fields](/fields/deleting-and-disabling) * [Core Fields vs. Custom Fields](/fields/core-vs-custom) # Deleting and Disabling Fields Source: https://help.qrtub.com/fields/deleting-and-disabling Core fields can only be disabled and always keep their data; a custom field can be deleted permanently, which leaves broken bindings and unreachable values behind. There are two ways to get a field off your Items, and which one you get depends on the kind of field. Core fields can only be disabled. Custom fields are deleted outright. Both actions happen on the chip strip in the Collection's settings, under **Fields**, and neither takes effect until you press **Save changes**. ## Disabling a core field Name, Item ID, Description, and Tags cannot be deleted — the × on the chip disables them instead. Disabling is a display decision, not a data one: * the field disappears from the Item form and the Items table, * every value already stored stays exactly where it is, * its Required flag is cleared, so re-enabling brings it back optional, * its default value stops being applied to new Items, * you can turn it back on any time from **Add More Fields**, values intact. Because they map to real database columns, the four core fields stay available to page bindings even while disabled — disabling hides the field from the people editing Items, not from the Page. A *custom* field that is switched off is a different story: it is dropped from the data a Page renders against, so a binding to it inserts an empty string and a condition referencing it evaluates to `false` with no error shown. ## Deleting a custom field A custom field's chip carries a trash icon, and it means it. QRtub asks you to confirm, and the warning is accurate on both counts: * **Page templates and Destinations that reference this field will show broken or unresolved bindings.** Nothing rewrites them for you the way a [rename](/fields/renaming-a-field) does. * **Existing Item data stored for this field becomes inaccessible.** The values are no longer readable anywhere: not in the table, not in an export, not by a binding. Creating a new field with the same key afterward does not recover them. A new field gets a new internal storage ID, so it starts empty — the old values stay stranded under the ID that was deleted. Treat deletion as one-way. Deleting a field does not delete any Items. They stay, minus that column. ## Which to reach for If you might want the data later, do not delete. Nothing stops you from leaving a field enabled and simply not filling it in, and a Collection carries no per-field cost for that. Custom fields that arrive from a Collection template or the **Add More Fields** library can sit in a disabled state, and those you can re-enable freely. But once a custom field is on the chip strip, the only removal action offered for it is Delete — there is no "hide this custom field" switch. ## Before you delete 1. Search your Destinations and Page sections for the field's key and remove or repoint those bindings. A binding left pointing at a deleted field inserts an empty string, so a URL built from it silently becomes wrong rather than visibly failing. 2. Export the Collection's Items to CSV first if the values are worth keeping. That export is the only copy you will have. 3. Then delete, and **Save changes**. ## Related * [Renaming a Field](/fields/renaming-a-field) * [Core Fields vs. Custom Fields](/fields/core-vs-custom) * [Creating a Custom Field](/fields/creating-a-field) * [Exporting Items to CSV](/import-export/exporting-items) # Field Defaults Source: https://help.qrtub.com/fields/field-defaults The Collection-level value that fills a field left blank when an Item is created — never retroactive, never overwriting what someone typed. A field can carry a default value, set once on the Collection and applied to Items as they are created. If the new Item leaves that field blank, the default fills it in. If the Item has a value of its own, the default is ignored. Set it in the Collection's settings, on the **Fields** tab: click the field's chip and fill in **Default value**. Press **Save changes** to store it. ## What "blank" means The default only fills a genuine gap. These all count as blank: * nothing entered at all, * an empty text box, * a list field with no values selected. Anything else is a real value and wins. A `0` in a number field or a deliberately cleared field is a value, not a gap. ## Defaults apply at creation only This is the part that surprises people: a default is stamped in when the Item is created and never revisited. * Changing the Collection's default later does **not** update Items that already exist. Their values were written at creation and stay as they were. * A CSV import applies defaults to rows that create a new Item, and **not** to rows that update an existing one. Otherwise a partial update — a file with only two columns in it — would quietly overwrite everything it omitted with Collection defaults. * A disabled field's default is skipped entirely. If you need existing Items brought in line with a new default, that is an edit to those Items: change them in the table, or export, edit, and re-import them. ## Two fields that never take a default **Item ID** cannot have one. It has to be unique within the Collection, so a shared default would collide on the second Item created. **The Destination URL** has a default, but it belongs to the Scan tab rather than the Fields tab, and it behaves slightly differently: when a new Item arrives without a destination of its own, the template is copied onto that Item, so each Item ends up owning its own copy. Editing the Collection's default afterward changes what new Items get and leaves existing ones alone. Field bindings inside that template — `{{item.item_id}}` and the like — are not frozen: they are resolved fresh on every scan against whatever the Item holds at that moment. See [Default Destination for New Items](/collections/default-destination) for how to author it. ## A worked example A Collection tracking rental plant sets the default on its `status` field to `available`. * Add an Item and leave status blank: it saves as `available`. * Add an Item and set status to `in_repair`: it stays `in_repair`. * Change the Collection default to `off_hire` next month: the two Items above do not move. The next Item created blank gets `off_hire`. ## Related * [Required Fields](/fields/required-fields) * [Allowed Values](/fields/allowed-values) * [Default Destination for New Items](/collections/default-destination) * [Importing Items from CSV](/import-export/importing-items) # Custom Field Types Source: https://help.qrtub.com/fields/field-types The six types a custom field can be, what each one gates, and how to choose between a fixed list of values (Allowed Values) and a live pointer to another record (Reference). A custom field is one of six types, chosen when you create it and changeable afterward. The type decides what the input looks like on the Item form, how the value is stored, and which of the field's other options you are allowed to switch on. ## The six types | Type | Stored as | On the Item form | Use it for | | ---------- | ------------------------- | ---------------------------------------------------------------------- | ------------------------------------------- | | **Text** | A string | A text box, or a picker if you give it allowed values | Serial numbers, locations, statuses, URLs | | **Number** | A number | A number box | Quantities, hours, meter readings | | **Date** | A date only, `YYYY-MM-DD` | A date picker | Installation date, warranty end | | **Yes/No** | `true` or `false` | A checkbox | Flags — insured, decommissioned | | **List** | An array of strings | A multi-select picker, or a comma-separated box with no allowed values | Anything an Item can have several of | | **UUID** | The ID of another record | A dropdown of records to point at | A responsible person, a parent Item, a site | A Date field holds no time of day. It is stored as `YYYY-MM-DD`, displayed in the format of whoever is looking at it, and a CSV import must use `YYYY-MM-DD` — other formats are rejected row by row. ## What each type gates Some options only appear for some types, which is the most common reason an option looks greyed out: * **Allowed Values** — Text and List only. On any other type the editor says so and hides the list. See [Allowed Values](/fields/allowed-values). * **Multiple Values** and **Allow New Values** — List only. Both checkboxes stay disabled until you switch the Field Type to List; the tooltip on each says the same thing. See [Allow New Values](/fields/allow-new-values). * **Reference configuration** — offered on a new field only when the type is UUID. See [Reference Fields](/fields/reference-fields). Multiple Values is what separates a single-select from a multi-select. With it off, a List field still uses a picker but keeps only the last value you choose; with it on, the field holds as many values as you select. ## Which type do I need? Start with what the value *is*: * **A quantity or reading** → Number, not Text. A Number field rejects anything that is not a number on CSV import; a Text field accepts whatever gets typed, typos included. * **A date** → Date, not Text, so it gets a date picker and a consistent stored format. * **One of a short, known set of options** → Text with allowed values (one value per Item), or List with allowed values and Multiple Values on (several per Item). * **Free text nobody will filter on** → Text with no allowed values. * **Another record already in QRtub** → UUID with a reference type. Anything else means retyping a name that will eventually go stale. ## Allowed Values or a Reference field? These are the two options people mix up, and the difference is where the value lives. **Allowed Values** is a fixed list of literal values you author on the field itself — `operational`, `in_repair`, `retired`. The Item stores one of those strings. You maintain the list by hand in the Collection's field settings. **A Reference field** holds no value of its own. It stores the ID of another record — a team member, another Item, or a Collection — and displays that record's current name and image. Change the referenced record's name and every Item pointing at it shows the new name, because nothing was ever copied. No allowed-values list applies to a reference field; the options in its dropdown are whatever records exist. So: a short vocabulary you invented is Allowed Values. A pointer at something that already exists elsewhere in QRtub is a Reference field. ## A note on UUID without a reference Choosing UUID and leaving the reference type unset gives you a plain text box, not a dropdown — the field has nothing to point at. Set the reference type as well, or pick Text instead. ## Related * [Allowed Values](/fields/allowed-values) * [Reference Fields](/fields/reference-fields) * [Creating a Custom Field](/fields/creating-a-field) * [Core Fields vs. Custom Fields](/fields/core-vs-custom) # Reference Fields Source: https://help.qrtub.com/fields/reference-fields The field that holds no value of its own — it stores a pointer to another Item, Collection, or team member and shows that record's current name and image. A reference field holds no value of its own. It stores the ID of another record in QRtub, and displays that record's current name and image. This is how you model a relationship: an Item that belongs to a site, or has an assigned owner. That is what separates it from [Allowed Values](/fields/allowed-values), which is a fixed list of literal values you author on the field itself. A reference field has no list to author — its options are whatever records exist, and it never copies their data. Rename the referenced record and every Item pointing at it shows the new name, because the name was never stored on the Item. ## Setting one up A reference field is a **UUID** field with a reference type set. When you create a custom field, choose UUID as the type and the reference configuration appears. Pick what the field points at: | Points at | Options offered in the dropdown | | ----------------- | ---------------------------------------------------------------- | | **A team member** | Everyone on the team | | **Another Item** | Items in this Collection, or Items in any Collection on the team | | **A Collection** | Any Collection on the team | For an Item reference, that second choice is the **Scope** setting: same Collection only, or any Collection in the team. Member and Collection references are always team-wide. **Searchable Dropdown** turns the picker into a search box instead of a plain list. Worth switching on for anything with more than a screenful of records, since the list is loaded in full and sorted alphabetically. ## What it looks like once it is set The picker and the Items table both show the referenced record rather than an ID: * a team member shows their avatar, name, and email, * an Item shows its image, its name, and its Item ID, * a Collection shows its image and name. If the referenced record can no longer be resolved — it was deleted, or it sits outside the field's scope — the cell falls back to a placeholder circle and the first characters of the stored ID. Nothing is cleared automatically, so that is your signal that a pointer has gone stale. ## Limits worth knowing before you commit **A binding inserts the ID, not the name.** `{{item.parent_item}}` in a Destination URL resolves to the stored record ID, because reference lookup happens in the app's own screens, not in the binding resolver. If you need a human-readable value in a URL, put it in a Text field. And remember that values are inserted into a URL exactly as stored, with no URL-encoding — a value containing a space or an `&` will break the link. If what you actually want in the URL is the Collection the Item belongs to, that is a Collection binding rather than a reference field: `{{collection.name}}`. **CSV import cannot fill a reference field.** A UUID field's CSV cell has to be a JSON object, so a bare record ID in that column is rejected as invalid. Set reference fields from the Item form. **A UUID field with no reference type is just a text box.** It has nothing to point at, so the form falls back to plain text input. If the dropdown never appears, the reference type is unset. ## Related * [Allowed Values](/fields/allowed-values) * [Custom Field Types](/fields/field-types) * [Creating a Custom Field](/fields/creating-a-field) * [Field Bindings](/destinations/field-bindings) # Renaming a Field Source: https://help.qrtub.com/fields/renaming-a-field Renaming a custom field is safe because its hidden storage ID never changes — and QRtub updates the page bindings, Destinations, and app-link fallbacks that referenced the old key. Renaming a custom field does not move any data and does not break the things pointing at it. You rename it by changing its label; the key follows. 1. Open the Collection's settings and go to the **Fields** tab. 2. Click the field's chip. 3. Edit **Custom Label**. The field key is regenerated from the new label — "Warranty End" on a field keyed `warranty_date` makes it `warranty_end`. 4. Click **Save**, then **Save changes** on the settings form. QRtub confirms the change as you save it, naming both keys: *Field key changed from "warranty\_date" to "warranty\_end".* ## Why it is safe Every custom field is created with a stable internal ID — an 8-character code you never see — and the Item's value is stored under that ID, not under the key. The key is a human-readable pointer to the ID. Renaming rewrites the pointer and leaves the storage alone, so there is no data migration, no export-and-reimport, and no window where values are missing. Two consequences follow. Renaming is instant even on a Collection with thousands of Items. And a field that is deleted and re-created with the same key is *not* the same field: it gets a new ID, and it cannot see the old field's data. ## What updates by itself **Page bindings.** The Page Editor shows you readable bindings like `{{item.warranty_date}}`, but stores them against the stable ID. A rename cannot break them; they simply display the new key next time you open the editor. **Destinations and renamed fields.** Destination URLs are stored with the readable key, so these genuinely would break — and QRtub rewrites them for you when you save the rename. Across every Item in the Collection it rewrites the Destination URL, the URL and condition of every conditional destination rule, the app-link fallback URL and message, and the Collection's own default destination template. Only Items that actually reference the renamed key are touched. This rewrite runs once, at the moment of the rename, using a before-and-after comparison of the field configuration. On the rare occasion an individual Item is missed, a later save will not retry it — the comparison shows no rename by then — so fix that Item's Destination by hand. **Conditions.** A condition typed against the field, whether on a page section or a destination rule, is covered by the two mechanisms above. This matters because a condition referencing a key that no longer exists does not raise an error: it evaluates to `false` silently, and the rule simply stops firing. ## What does not update **A CSV file you already have.** An export's column headers come from each field's label, and an import matches a header back by label or by key — both of which the rename just changed. So a file exported beforehand now carries a column QRtub does not recognize, and its rows are rejected as an unknown column. Export the Collection again to get a file with current headers, or edit that one header by hand. **Anything outside QRtub.** The rename changes your field's key, not the parameter names of the system you are sending values to. A URL like `https://example.com/asset?sn={{item.warranty_end}}` has its binding rewritten; the `sn=` part is yours to maintain. ## What cannot be renamed Core fields — Name, Item ID, Description, and Tags — have dedicated database columns rather than an internal ID, so both their key and their label are locked. The field editor marks them as such. A rename is also refused if the new key is already in use in the Collection, or breaks any of the [field key rules](/fields/creating-a-field). The error names the conflict and nothing is changed. ## Related * [Creating a Custom Field](/fields/creating-a-field) * [Core Fields vs. Custom Fields](/fields/core-vs-custom) * [Deleting and Disabling Fields](/fields/deleting-and-disabling) * [Field Bindings](/destinations/field-bindings) # Required Fields Source: https://help.qrtub.com/fields/required-fields The Required checkbox on a field, what counts as blank, and the one carve-out: a CSV row updating an existing Item is only checked on the columns it actually contains. Any field can be marked required, core fields included. Tick **Required** on the field's chip in the Collection's **Fields** tab and press **Save changes**. From then on the field's label carries an asterisk on the Item form, and an Item cannot be saved without it. ## Where it is enforced Two places, with the same definition of "missing": * **The Item form**, on both create and edit. Saving with a required field blank shows "*Field* is required" against that field and the Item is not saved. * **CSV import**, row by row. A row missing a required value is rejected and named in the import report; the rest of the file still imports. A value counts as missing when it is null, an empty text box, a blank number, or a list field with nothing in it. An empty list is missing, not present — a required Tags field means at least one tag. ## Only enabled fields are enforced Required is ignored on a disabled field. That combination is easy to arrive at by accident: if you disable a core field, QRtub clears its Required flag at the same time, so re-enabling it later brings it back optional. Re-tick Required if you still want it. ## The CSV partial-update carve-out This is the behavior most likely to catch you out, and it is deliberate. When a CSV row **creates** an Item, every required field on the Collection has to be present and filled in that row. When a CSV row **updates** an existing Item — because its `id` matches one already in the Collection — required fields are only checked for the columns that row actually contains. A two-column file that updates nothing but `status` will not be rejected over a required `serial_number` column it never mentioned. Without that carve-out, no partial update would ever be possible: any file narrower than the full set of required columns would fail on every row. The trade-off is that a partial update cannot be used to *notice* an existing Item with a required field left blank — nothing is re-validated except what you sent. The same rule applies to the Item ID format check when a Collection mints its links from a numbered pattern: an update row that omits `item_id` is not asked to prove anything about the Item ID the Item already has. ## Choosing what to require Require the fields a scan depends on. If a Destination URL is built from `{{item.serial_number}}`, an Item with no serial number produces a broken link — the binding inserts an empty string rather than failing loudly. Making that field required is the cheapest place to catch it. Conditions behave the same way. An undefined identifier makes a whole condition evaluate to `false` silently, with no error shown, so a Destination gated on a field nobody filled in simply never appears. ## Related * [Field Defaults](/fields/field-defaults) * [Creating a Custom Field](/fields/creating-a-field) * [Deleting and Disabling Fields](/fields/deleting-and-disabling) * [Importing Items from CSV](/import-export/importing-items) # Arboriculture and tree management Source: https://help.qrtub.com/for/arboriculture Where QRtub fits for tree populations: what gets tagged, when it is worth it, the problems you'll hit, and the software it points at. A tree is a long-lived asset in a public place, inspected on a cycle by people who are not the people who notice it. That combination is unusual, and it is what makes tags on trees behave differently from tags on plant. ## Where QRtub fits You are tagging something that will outlive several contracts and probably several software choices. A tag nailed to a street tree in 2026 needs to still resolve when the works history has moved platforms twice and the contractor has changed. QRtub holds the address, so the tag stays put and what it opens is a setting. ## What gets tagged * Street and park trees, individually numbered * Significant and heritage trees * Recent plantings under establishment maintenance * Trees on strata and commercial property under a management contract ## QRtub is particularly useful when * **The tag has to outlive the contract.** Management moves between contractors; the numbering on the tree does not. * **The same tree is inspected by staff and noticed by the public.** Two audiences, one tag — see [One tag, your team and the public](/how/team-and-public). * **The population changes constantly.** Plantings, removals, storm damage. Codes can be reserved and produced in batches before the next round of planting is decided. * **Tags go somewhere anyone can reach them.** Unlike plant in a yard, a street tree is scanned by residents, which is either wasted or useful depending on what is behind it. * **The trees are numbered in the thousands** and the register has to survive staff turnover. ## The problems you'll hit In the order they usually arrive: 1. [One tag, your team and the public](/how/team-and-public) — the crew's inspection form and a public reporting route from the same tag 2. [Make the installation earn its keep](/how/earn-its-keep) — species, planting date and who maintains it, rather than a locked spreadsheet 3. [Let anyone report a fault](/how/report-a-fault) — a resident reporting a hanging limb ## Works with The technical detail for each lives on its own page. This is only which tool fills which slot. | Tool | What a scan opens | | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | **Mitti** | The tree's inspection template, or its record — [guide](/integrations/mitti/setup) | | **Google Forms** | A public reporting form, pre-filled with the tree number — [guide](/integrations/google-forms/prefill) | | **Google Maps** | The tree's location from its own coordinates — [guide](/integrations/google-maps) | | **Arborcheck · TreePlotter · CONFIRM · TreeWorks** | Their own record for that tree. Any of them with a per-tree URL works; see [What Is a Destination?](/destinations/what-is-a-destination) | | **Council GIS and work-order systems** | The spatial record or the open job | ## Typical Item fields Tree number · species (botanical and common) · planting date · location and coordinates · last inspection · next inspection due · works history reference · ownership or management contract Species and ownership are the two worth making [Allowed Values](/fields/allowed-values), because they are the two that get typed three different ways. ## Related * [What Is a Tag?](/tags/what-is-a-tag) — choosing something that survives outdoors * [Choosing a Tag Type](/tags/choosing-a-tag-type) * [Reserve Links in bulk](/links/numbered-links) # Construction Source: https://help.qrtub.com/for/construction Where QRtub fits on a construction site: plant that changes hands daily, subcontractors with no logins, and tags that have to survive the job. On a construction site the person who needs the information usually does not work for the company that holds it. ## Where QRtub fits Site software assumes accounts. Inductions, prestart records, permits and plant registers all sit behind a login belonging to the principal contractor — which is right for the record, and useless for the subcontractor's operator standing in front of the machine at six in the morning. QRtub puts the address on the plant itself. What the code opens can be the prestart form today and a different one when the site's systems change, without going back around the yard. ## What gets tagged * Plant and machinery, hired and owned * Power tools and leads carrying test tags * Height safety equipment — harnesses, lanyards, anchor points * Scaffold, formwork and temporary works * Site sheds, switchboards and generators * Materials and prefabricated elements awaiting installation ## QRtub is particularly useful when * **Subcontractors operate your plant.** They will not be issued accounts in your systems for a three-week package, and a prestart nobody can complete is a prestart that does not happen. * **The same machine moves between sites** run by different principals, each with different software. * **Inspections repeat on a cycle** — quarterly on leads, six-monthly on height safety — and the physical tag is already the accepted way of showing the last one. * **A defect needs reporting by whoever finds it**, not by whoever has the app. See [Let anyone report a fault](/how/report-a-fault). * **You are printing before the register is finished.** Plant arrives over months; codes are cheapest produced in one run. * **Something has to point at a document, not a system** — a plant risk assessment, an operating procedure, a lift plan. ## The problems you'll hit 1. [One tag, your team and the public](/how/team-and-public) — your supervisor and a subcontractor's operator from one code 2. [Let anyone report a fault](/how/report-a-fault) — defects raised without an account 3. [An on-hire flag](/how/on-hire-flag) — plant that is yours this month and hired the next 4. [Make the installation earn its keep](/how/earn-its-keep) — a tag that survives the job ## Works with | Tool | What a scan opens | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | **Mitti** | A prestart or plant inspection template — [guide](/integrations/mitti/setup) | | **Google Forms** | A free prestart or defect form, no account needed — [guide](/integrations/google-forms/overview) | | **Jotform** | The same with photos and a signature — [guide](/integrations/jotform) | | **MaintainX** | A maintenance request from the machine — [guide](/integrations/maintainx) | | **SharePoint or Google Drive** | Risk assessments, procedures, plans — [Microsoft 365](/integrations/microsoft-365) · [Drive](/integrations/google-workspace) | | **YouTube** | A short operating or safety video — [guide](/integrations/youtube) | | **Google Maps** | Where a piece of plant is meant to be — [guide](/integrations/google-maps) | A plant register in a spreadsheet is a perfectly good starting point. What QRtub adds is that the machine can reach its own row. ## Typical Item fields Plant number · description · make and model · serial · owner or hire company · current site · prestart template · last inspection · next test due · risk assessment URL ## Related * [What Is a Tag?](/tags/what-is-a-tag) — what survives concrete dust and a wash-down * [Field Bindings](/destinations/field-bindings) — carrying the plant number into the form # Equipment hire Source: https://help.qrtub.com/for/equipment-hire Where QRtub fits for hire fleets: what gets tagged, when it is worth it, and how one code serves your yard and somebody else's site. Hire is the trade where the same machine is scanned by two different companies in the same month, and neither has a login to the other's systems. ## Where QRtub fits Hire software is built around the contract — on hire, off hire, pre-hire and post-hire inspection, damage at collection, sign-off on delivery. All of that assumes the person doing it works for you. The gap is the fortnight in between, when the machine is on a site you do not control and the person standing next to it is the hirer's operator. QRtub holds the address on the machine, so what that code opens can be your fitter's view today and the hirer's pre-start form tomorrow. ## What gets tagged * Plant and access equipment out on hire * Attachments and ancillaries, which go missing more often than the machine * Generators, compressors, pumps, power leads * Workshop and service items not currently on hire * Cross-hired equipment you do not own ## QRtub is particularly useful when * **The same machine goes out to several companies a quarter**, each running different software. * **You cross-hire in and out.** Somebody else's machine on your contract, or yours on theirs. See [An on-hire flag](/how/on-hire-flag). * **A pre-start check has to be possible for someone with no account.** A hirer's operator will not be set up in your system for a two-week hire, and should not need to be. * **Damage disputes turn on what condition it left in.** A form the hirer can fill in, with photos, from the machine itself, is worth more than a signature on a delivery docket. * **Attachments outnumber machines** and are the hardest thing to keep a register of. * **The fleet changes constantly** — bought, sold, written off, cross-hired — so a tag population is never in step with the asset register. ## The problems you'll hit 1. [An on-hire flag](/how/on-hire-flag) — the same tag showing your buttons in the yard and the hirer's on site 2. [One tag, your team and the public](/how/team-and-public) — your fitter and the hirer's operator from one code 3. [Let anyone report a fault](/how/report-a-fault) — damage reported from the site, not at collection 4. [Make the installation earn its keep](/how/earn-its-keep) — a plate on a machine with your name on it, in front of somebody else's crew ## Works with The URL detail for each is on its own page. This is which tool does what. | Tool | What a scan opens | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | **Jotform** | A pre-start or damage form the hirer can complete with no account, with photos and a signature — [guide](/integrations/jotform) | | **Google Forms** | The same, free, but **file upload requires a Google sign-in** — see [Google Forms](/integrations/google-forms/overview) | | **Mitti** | Your own inspection templates and asset records — [guide](/integrations/mitti/setup) | | **MaintainX** | A maintenance request from the site, no account needed — [guide](/integrations/maintainx) | | **Your hire system** | The asset or contract record. Anything with a per-asset URL works | That Google Forms limitation matters here more than anywhere: damage evidence is photos, and a form that demands a sign-in before accepting one will not get used on somebody else's site. ## Typical Item fields Fleet number · make and model · serial · **on hire** (Yes/No) · current hirer · off-hire date · last inspection · next service due · workshop status · owned or cross-hired Fleet number and on hire are the two that earn a [Field Default](/fields/field-defaults) — the first because it is what everyone calls the machine, the second because an unset flag behaves differently from a false one. ## Related * [What Is a Tag?](/tags/what-is-a-tag) — surviving a wash-down and a fortnight on site * [Reserve Links in bulk](/links/numbered-links) # Facilities and grounds Source: https://help.qrtub.com/for/facilities Where QRtub fits for facilities, cleaning and grounds teams: equipment in buildings, faults reported by whoever finds them, and contractors with no login. Facilities is the trade where most of the people who notice a problem are not employees, do not have the app, and will not be getting an account. ## Where QRtub fits A facilities system holds the asset register, the planned maintenance schedule and the work order history. Everyone who works in the building sits outside it — tenants, students, residents, visitors, cleaners and the contractor who turns up once a quarter. A code on the plant, the toilet block or the drinking fountain gives that outside group one place to go. Behind it, your own team can see what they need and everyone else sees only what you have chosen to show. ## What gets tagged * Plant rooms, switchboards, pumps and air conditioning units * Fire equipment — extinguishers, hose reels, exit lighting * Lifts, doors, gates and access control hardware * Amenities: toilet blocks, drinking fountains, barbecues, shelters * Playgrounds, park furniture, bins and signage * Cleaning equipment and consumable stores ## QRtub is particularly useful when * **The person who spots the fault is not on your staff.** A tenant, a resident or a member of the public reporting a broken fountain is the fastest fault detection you will ever get, and it costs nothing to enable. See [Let anyone report a fault](/how/report-a-fault). * **Contractors attend unsupervised.** A code at the plant gives them the procedure and a place to record attendance without an account on your system. * **Assets are scattered across sites** and nobody can be expected to find the right record by navigating a list of four hundred. * **The same item needs a staff view and a public view.** See [One tag, your team and the public](/how/team-and-public). * **Inspections are already tagged physically.** Fire equipment and test-and-tag cycles have carried a card on the item for decades — the code goes on the same spot. * **Assets outlive the software.** A pump installed in 2014 has outlasted two maintenance systems. The code should outlast the third. ## The problems you'll hit 1. [Let anyone report a fault](/how/report-a-fault) — the central one for this trade 2. [One tag, your team and the public](/how/team-and-public) — occupants and technicians on one code 3. [Make the installation earn its keep](/how/earn-its-keep) — a code in a public place carries more than a form ## Works with | Tool | What a scan opens | | ------------------------ | ------------------------------------------------------------------------------------------------------ | | **Google Forms** | A free fault report anyone can submit — [guide](/integrations/google-forms/overview) | | **Jotform** | A fault report with a photo, no account needed — [guide](/integrations/jotform) | | **MaintainX** | A work request straight into maintenance — [guide](/integrations/maintainx) | | **ServiceM8** | A job for a contractor attending — [guide](/integrations/servicem8) | | **Mitti** | Inspection templates and asset records — [guide](/integrations/mitti/setup) | | **WhatsApp** | A message to the on-call number, prefilled with which asset — [guide](/integrations/whatsapp) | | **Notion or SharePoint** | Procedures and manuals — [Notion](/integrations/notion) · [Microsoft 365](/integrations/microsoft-365) | | **YouTube** | How to reset it before anyone is called out — [guide](/integrations/youtube) | The WhatsApp one is worth a look for out-of-hours. A message that already says which pump it is beats a phone call that starts with working out which pump it is. ## Typical Item fields Asset number · description · building and level · location detail · make and model · installed date · service contractor · last service · next service due · manual URL · public or staff only ## Related * [Conditional Visibility](/destinations/conditional-visibility) — showing staff buttons only to staff * [What Is a Tag?](/tags/what-is-a-tag) — outdoors, in public, for years # Marine and workboats Source: https://help.qrtub.com/for/marine Where QRtub fits for a workboat fleet: why stickers do not survive, why one code has to reach several systems, and why the boat has to be tagged before it exists in software. A workboat is inspected by its master, serviced by a mechanic, surveyed by a regulator and audited by a client — four groups, three systems, and one hull. ## Where QRtub fits A fleet of around thirty aluminum workboats runs like this. The boats are assets in one platform, where masters record pre-operation checks and raise actions and in-house mechanics record outboard services. The compliance documents — survey and survey-exemption certificates — live in an entirely different system, which most staff have no easy access to. So the code on the hull has to reach both. That is the shape QRtub is for: one address per boat, several destinations behind it, and the choice of which is a setting rather than something decided when the plate was made. ## What gets tagged * Hulls, at the helm and at the transom * Outboards and inboard engines, serviced on their own cycle * Trailers, which move between boats * Safety equipment with expiry dates — lifejackets, EPIRBs, extinguishers * Ancillary gear that leaves the boat and comes back ## QRtub is particularly useful when * **Nothing adhesive survives.** Salt water, UV, wash-down and hard use mean stickers last weeks. Photo-anodized aluminum riveted to the hull is the only reliable answer — and it is not economical to produce one at a time. * **The boat has to be tagged before it exists in software.** A new vessel cannot be given a code that points at an asset record and a compliance file it does not yet have. * **Compliance lives somewhere most staff cannot reach.** A certificate everyone needs, in a system only administrators use, is a certificate nobody reads. * **People pick the wrong asset.** Navigating an inspection app by hand to find one of thirty similar boats produces inspections filed against the wrong hull — which is worse than a missing inspection, because it looks like compliance and is not. A scan of that boat's own plate cannot choose wrongly. * **The fleet is spread across the country** and the person holding the phone is not the person who set the system up. ## The problems you'll hit 1. [One tag, your team and the public](/how/team-and-public) — masters, mechanics, surveyors and clients from one plate 2. [Make the installation earn its keep](/how/earn-its-keep) — a plate that reaches the certificate, not just the asset record 3. [Let anyone report a fault](/how/report-a-fault) — a defect raised from the water ## Works with | Tool | What a scan opens | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | | **Mitti** | The boat's asset profile, a pre-operation check, or a service template — [guide](/integrations/mitti/setup) | | **A compliance system** | The survey or exemption certificate. Store its per-boat URL in a field and bind it — see [Field Bindings](/destinations/field-bindings) | | **Google Drive or SharePoint** | Manuals and schematics — [Drive](/integrations/google-workspace) · [Microsoft 365](/integrations/microsoft-365) | | **Google Forms or Jotform** | A defect report anyone aboard can send | The pattern worth copying from that fleet: **one text field per external system**, holding that boat's own URL or ID, with the Destination built from it. Adding a second system later is a field and a button, not a re-plate. ## Typical Item fields Vessel name · fleet number · hull identification · asset ID in your inspection platform · compliance record URL · survey expiry · engine hours · home port · last pre-operation check ## Related * [What Is a Tag?](/tags/what-is-a-tag) — anodizing, engraving and what survives salt water * [Produce before you know where they go](/links/numbered-links) — reserving codes for boats not yet in any system * [Choosing a Method](/suppliers/choosing-a-method) — why one plate at a time is uneconomical # Send iPhone and Android to the right app store Source: https://help.qrtub.com/how/app-store-link One code that opens the App Store on an iPhone and Google Play on an Android, instead of showing both badges and hoping. Every app on the web is advertised with two badges side by side, because a printed link cannot know what phone is holding it. One of the two is always wrong for whoever is looking. A scan can know. The phone tells you what it is. ## How it works Two Destinations on the same code, each shown only to the phone it suits. | Destination | URL | Show When | | ------------------------- | ----------------------------------------------------------- | ------------------ | | Download on the App Store | `https://apps.apple.com/app/yourapp` | `device.isIOS` | | Get it on Google Play | `https://play.google.com/store/apps/details?id=com.yourapp` | `device.isAndroid` | An iPhone sees one button. An Android sees the other. Nobody sees a choice they cannot use. The conditions go in the **Visibility** group when you select the section — see [Conditional Visibility](/destinations/conditional-visibility) and [Device Detection & Routing](/destinations/device-detection) for everything a condition can read about the device. ## Add a third for everyone else A desktop browser, a tablet, or a phone QRtub cannot identify all fall outside both conditions and would see nothing at all. Leave one Destination with **no condition** on it: ``` ├── Download on the App Store device.isIOS ├── Get it on Google Play device.isAndroid └── Open in your browser (no condition — always shows) ``` **When the device cannot be identified, QRtub assumes desktop.** So the unconditioned button is not a nicety; it is what an unrecognised phone gets. ## What it needs * Two store URLs, which you already have * One condition on each * One button with no condition, as the fallback Nothing about the code changes, so a tag already printed can be given this by editing its [Page](/pages/pages-overview). ## Where this stops being the right tool This is a good use of a device condition because the answer really is about the *device*. Your app genuinely only installs from one store. It is the wrong tool the moment the question is about the *person* — which staff see one thing and customers another. A device condition cannot tell those apart: someone in the field on a laptop gets the desktop branch, and someone at a desk on their phone gets the mobile one. For that, see [One tag, your team and the public](/how/team-and-public). ## Related * [Device Detection & Routing](/destinations/device-detection) * [Conditional Visibility](/destinations/conditional-visibility) * [App Links & Fallback URLs](/destinations/app-links) — for opening an app you have already installed # Make the installation earn its keep Source: https://help.qrtub.com/how/earn-its-keep A permanent tag that opens one locked file is doing almost nothing. What else can sit behind it, and why the moment someone scans is the hard part to buy. Someone scanned a row of tree tags in a park. Each one opened a secure Google Sheet — no branding, no public access, one destination for one audience. Durable tags, properly installed, on public infrastructure, and a locked door behind every one of them. The physical work was done well. Then it stopped. ## The thing being wasted is the scan Getting somebody to voluntarily point their phone at your equipment is the hardest part of any channel, and it already happened. They are standing in front of the thing, curious, holding an unlocked phone. A tag that meets that with a login screen has spent the money and skipped the return. ## How it works Add the things the scan is worth to the same [Page](/pages/pages-overview). Nothing comes off the tag, and nothing is produced twice. ``` Tree 4412 — London Plane ├── Species and planting date on the Page itself ├── Who maintains this tree your name, and why it matters ├── Report a problem open to anyone └── Works history your team's tool, their sign-in ``` The crew still taps through to the tool they use. Everyone else gets something. ## What goes where | | What it does | Options | | ---------------------- | ------------------------------------ | -------------------------------------------------------------------- | | **Context** | What the thing is, in plain words | Text, an image and Item fields on the Page — no external tool needed | | **Your name on it** | A professional did skilled work here | Page [theming](/pages/page-theming) and a logo | | **A way to respond** | Turn a scan into something useful | See [Let anyone report a fault](/how/report-a-fault) | | **The internal route** | Unchanged, still protected | Your inspection app or asset system | ## Context costs nothing to add The first row is the cheapest and most overlooked. Species, planting date, capacity, serial, who services it — that data is already on the Item, and putting it on the Page is a section, not an integration. If the only thing you do is stop a public tag being a dead end, that is most of the value here. ## What it needs * One Page rather than a direct redirect — see [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode) * Item fields you almost certainly already have * One decision: what you are willing to publish Nothing produced again. An installed tag can be given all of this by editing its Page. ## The tag is the smallest part of the job An anodised plate is not cheap, and neither is installing five hundred of them. What sits behind them is a text field and an afternoon, and it is the difference between a tag that identifies something and a tag that does something. ## Related * [One tag, your team and the public](/how/team-and-public) * [Let anyone report a fault](/how/report-a-fault) * [Pages Overview](/pages/pages-overview) # Change what a tag does when the machine goes out on hire Source: https://help.qrtub.com/how/on-hire-flag One tick box on the Item hides your internal buttons and shows a form the hirer can use, then puts everything back when the machine returns. A machine leaves your yard for a fortnight. While it is away, the person scanning it is not your fitter — it is somebody at another company, running different software, who has no login to anything of yours. The tag on the machine cannot change. What it does can. ## How it works Add one Yes/No field to the Item, then let two groups of buttons watch it. | The field | | | --------- | --------------------------------------------- | | Label | **On hire** | | Type | **Yes/No** — a tick box, made for flags | | Field key | `on_hire`, which gives you `{{item.on_hire}}` | Then, in the [Page Editor](/pages/page-editor-layout), put your internal buttons inside one **Container** and the hire buttons inside another, and give each container a condition in the **Visibility** group: ```text theme={null} Internal container Show When: item.on_hire != true Hire container Show When: item.on_hire == true ``` A Container hides its children with it, so that is two conditions for the whole page rather than one per button. Now the tag reads differently depending on one tick box: ``` In the yard Out on hire ├── Start pre-start check ├── Pre-start check (a form, no login) ├── Service history ├── Operator manual ├── Asset record └── Report a problem └── Report a problem ``` Tick the box when the machine goes out. Untick it when it comes back. Nothing physical is touched and nothing is produced again. ## What goes where | | What it does | Options | | ------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | **Your internal buttons** | Where your own team records work | Your asset system, CMMS or inspection app — [Mitti](/integrations/mitti/setup) · [MaintainX](/integrations/maintainx) | | **The hire buttons** | Something the hirer can actually open | [Jotform](/integrations/jotform) · [Google Forms](/integrations/google-forms/overview) · a PDF manual on any file host | | **The flag** | Which set is showing | One Yes/No field on the Item | | **Always visible** | Things both sides need | A reporting route, and what the machine is | The hire buttons are the point: a form on [Jotform](/integrations/jotform) or [Google Forms](/integrations/google-forms/overview) can be filled in by anyone, so the hirer's crew can complete a pre-start check without you setting up a single account for them. ## Set a default, or existing Items will surprise you Add a Yes/No field to a Collection that already has Items and those Items have no value for it — not `false`, nothing. A condition testing `== false` would then hide your internal buttons on every machine you already own. Two things avoid it: * Give the field a **[Field Default](/fields/field-defaults)** so no Item is ever unset. * Write the internal condition as `item.on_hire != true` rather than `== false`, so anything that is not explicitly ticked counts as in the yard. Check it before you rely on it. The Visibility field shows a **Visible** or **Hidden** badge against whichever Item you have selected, so switch to a real machine rather than trusting the base template — see [Conditional Visibility](/destinations/conditional-visibility). ## What it needs * One Yes/No field on the Collection, with a default * Two Containers on the Page, one condition each * A form the hirer can open without an account * Somebody to tick the box. This is the real cost: it is a step in your hire-out process, and a machine that goes out with the box unticked shows the hirer buttons they cannot use ## Why not just give them a login You can, and for a long-term hire you probably should. This is for the fortnight — where setting up an account, having it approved, and remembering to remove it costs more than the hire earns, and where the machine is going to three different companies this quarter. ## Related * [One tag, your team and the public](/how/team-and-public) * [Conditional Visibility](/destinations/conditional-visibility) * [Field Defaults](/fields/field-defaults) * [Equipment hire](/for/equipment-hire) # Let anyone report a fault Source: https://help.qrtub.com/how/report-a-fault Giving the person who spots a problem a way to tell you, without an account, an app, or knowing who to email. Whoever notices a fault is usually not on your team. A resident sees a broken gate, a driver finds a damaged roller door, a tenant reports a tap. They are standing in front of the thing, they know exactly which one it is, and they have no way to tell you. Most of them will not look up a phone number. They will take a photo and forget. ## How it works Put a form on the tag, and make sure the form already knows which thing it is about. ``` Gate 7 — North car park ├── Report a problem → a form anyone can submit └── About this gate → what it is, who maintains it ``` The person taps once, describes the problem, and sends it. They never sign in and never choose which asset it was, because the code told the form. ## What goes where Whatever you already run. The examples are not a closed list. | | Options | | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **The form** | [Google Forms](/integrations/google-forms/overview) · [Jotform](/integrations/jotform) · a Mitti issue code · a [MaintainX](/integrations/maintainx) request portal | | **A conversation instead of a form** | [WhatsApp](/integrations/whatsapp), with the message already written | | **Where the report lands** | Wherever that tool already sends things — an inbox, a spreadsheet, a requests queue | ## Say which thing it was This is the part worth getting right. A form that arrives saying only "the gate is broken" costs someone a phone call. A form that arrives knowing it was Gate 7 does not. Carry the identifier into the form with a [field binding](/destinations/field-bindings) so every tag opens the same form pre-filled with its own Item's details — see [Pre-filling a Google Form](/integrations/google-forms/prefill). Bind an identifier, never a description. Values go into a URL exactly as stored, so a field containing a space or an `&` breaks the link. ## What it needs * One form, open to anyone. Check that: a Workspace form restricted to your organisation, or one limited to a single response, will turn people away. * One Destination on the tag. * Nothing produced twice. A tag already installed can be given a reporting route by editing its [Page](/pages/pages-overview). ## What to expect Reports from people you cannot identify, which is the point and also the cost. Some will be duplicates, a few will be wrong, and one will be the thing you needed to know a week earlier than you would have. If that becomes a problem, the answer is a required field on the form rather than a barrier in front of it. ## Related * [One tag, your team and the public](/how/team-and-public) * [Make the installation earn its keep](/how/earn-its-keep) # One tag, your team and the public Source: https://help.qrtub.com/how/team-and-public A pattern for a tag anyone can scan: the operational buttons your crew needs, and a route for whoever else finds it, on the same Page. A tag installed somewhere public gets scanned by people you did not plan for. A resident, a delivery driver, a client's site manager, someone who simply noticed it. The common failure is a permanent tag that opens one thing only your team can use. The tag is installed, expensive and idle: everyone else meets a sign-in screen and leaves, and nothing is captured from the one moment they were paying attention. ## The shape One [Page](/pages/pages-overview), carrying every Destination either audience might want. Everyone who scans sees the same buttons and picks what they came for. ``` Playground 14 — Riverside Park ├── Start inspection → your team's tool ├── Works history → your team's tool ├── Report a problem → open to anyone, no account └── About this asset → text and a photo on the Page itself ``` Your crew taps through to the tools they already use. Anyone else reads what you published and uses the reporting route. ## The slots Each row is a role in the pattern. Fill it with whatever you already run — the examples are not a closed list. | Slot | What goes here | Examples | | ---------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **The team's tool** | Where work gets recorded | [Mitti](/integrations/mitti/setup) · [MaintainX](/integrations/maintainx) · [ServiceM8](/integrations/servicem8) · any CMMS or inspection app | | **The public's route** | Somewhere anyone can submit with no account | [Google Forms](/integrations/google-forms/overview) · [Jotform](/integrations/jotform) · a Mitti issue code · a [MaintainX](/integrations/maintainx) request portal · [WhatsApp](/integrations/whatsapp) | | **The reference** | Something people need to read | [Google Drive](/integrations/google-workspace) · [Microsoft 365](/integrations/microsoft-365) · [Notion](/integrations/notion) · Dropbox · any file host | | **The context** | What the thing is, in plain words | Text, an image and Item fields on the Page itself — no external tool | ## Nothing is exposed by putting the buttons side by side The reflex is to worry that a public tag showing operational buttons leaks something. It does not. QRtub holds the address, never the data, so **every Destination keeps its own permissions exactly as they are.** Someone outside your organisation who taps the inspection button meets your tool's sign-in, because protecting those records is that tool's job and it is still doing it. Putting a code on something grants nobody anything they did not already have. So the decision is not about risk. It is about **what you want to offer** the people you did not plan for. See [What Is a Destination?](/destinations/what-is-a-destination). ## What it costs One Page and one open form. No extra Links, no second tag, and nothing produced twice — a tag already in the field can be given the public route by editing its Page. The one thing worth deciding before you produce a Batch: whether the reference slot is readable by an outsider. A file set to your organisation only is fine as the team's copy, but it should not be the *only* thing a public scan can reach. ## Related * [Make the installation earn its keep](/how/earn-its-keep) * [Let anyone report a fault](/how/report-a-fault) * [Pages Overview](/pages/pages-overview) # Exporting Items to CSV Source: https://help.qrtub.com/import-export/exporting-items Download a Collection's Items as CSV — visible columns or a full-field backup — scoped by whatever search, filter and sort the items table is showing Exporting writes a Collection's Items to a CSV file you can open in a spreadsheet, edit, and upload back. Open the Collection, use the **Download / Upload List** menu above the items table, and pick one of the two download options. This is the Item list. It is not the print list a [print batch](/print-batches/csv-download) produces — that file describes Links and codes for a supplier and contains different columns. ## The two options **Download Visible Columns** exports exactly the columns currently shown in the items table. Use it when you want a working file for a specific job — a stocktake sheet, a list to send someone — and want to keep the columns you already arranged on screen. **Download All Columns (Backup)** exports every field configured on the Collection, in the order the fields are arranged, including fields that happen to be empty on every Item. It also always includes the Destination URL column and the app-link fallback columns, so a restore can seed those again. Use it as a backup or when you plan to edit and re-import. ## The export follows what you are looking at Whatever search, filters and sort order the items table has applied carries into the file. Filter to one site and you export that site. Clear the filters first if you want everything. Filtering affects rows, not columns, and pagination does not apply: every matching Item is exported, not just the page you can see. ## What the file looks like * **`id` is always the first column.** That is what makes a re-import update the same Items instead of creating duplicates, so keep it if you plan to upload the file back. * **Headers use each field's configured label** — a field relabeled to "Plant No." exports under that heading. If two fields would produce the same heading, the second falls back to its field key so no two columns collide. Import recognizes either form. * **List values, such as Tags, are joined with `; `** in a single cell. * **Dates export as ISO `YYYY-MM-DD`**, regardless of how they are displayed on screen, and yes/no fields export as `true` or `false`. * **Fields no longer on the Collection are left out.** Data left behind by a deleted field is not exported. * **The Item photo is never exported.** Import ignores it too, so there is nothing to round-trip. The file is named after the Collection and the date — `Heavy_Equipment_2026-08-18.csv` — with any character that is not a letter, number, hyphen or underscore replaced by an underscore. ## Exporting an empty Collection gives you a template A Collection with no Items still exports a file with the full header row when you choose the backup option. That is a convenient starting template: download it, fill in the rows, and [import it](/import-export/importing-items). ## One thing to fix before re-importing Values beginning with `=`, `+`, `-`, `@`, `|` or a tab are exported with a leading apostrophe, so a spreadsheet cannot execute them as formulas. The apostrophe is not removed on import, because QRtub cannot tell it apart from an apostrophe you meant to store. The practical consequence: a negative number such as `-40` exports as `'-40`, and re-importing it into a number field is rejected as an invalid number for that row. Strip the apostrophe from those cells before uploading. ## Related * [Importing Items from CSV](/import-export/importing-items) * [What Is an Item?](/items/overview) * [Keywords](/items/keywords) # Importing Items from CSV Source: https://help.qrtub.com/import-export/importing-items Bulk create and update Items in a Collection from a CSV file: the 10 MB / 10,000-row limits, the dry-run preview, and what each row is validated against A CSV import creates and updates Items in one Collection in bulk. Open the Collection, use the **Download / Upload List** menu above the items table, and choose **Upload CSV**. This is the Item list — the same data the items table shows. It is a different feature from the print list a [print batch](/print-batches/overview) produces: that CSV describes Links and codes to send to a supplier and is never uploaded back here. ## File requirements | Requirement | Limit | | --------------- | --------------------------------------- | | File type | Must end in `.csv` | | File size | 10 MB maximum | | Rows | 10,000 data rows maximum | | Minimum content | A header row plus at least one data row | Exceed a limit and the whole upload is refused with a message saying which one — nothing is partially imported. Column headers are matched to the Collection's fields case-insensitively, by either the field's key (`serial_number`) or its label ("Serial Number"). **A column that matches nothing is an error**, and the rows carrying it are rejected, so the easiest way to build a valid file is to [export the Collection first](/import-export/exporting-items) and edit what comes back. ## Each row creates or updates — nothing is deleted The `id` column decides which. A row whose `id` matches an existing Item in this Collection updates that Item; a row with a blank or unrecognized `id` creates a new one. An import never deletes an Item, and there is no replace mode here — the destructive [Collection backup import](/collections/import-backup) is a separate feature. If the same `id` appears twice in one file, the first occurrence is used and the later ones are rejected as duplicates. ## Partial updates are safe On an update row, columns you left out of the file are preserved rather than blanked. A column that is present but empty is treated as a deliberate "clear this value". Two related behaviors follow from that: * Required fields are only enforced on an update row for columns actually present in that row, so a partial update cannot be rejected over an unrelated required field it never touched. * Collection-level field defaults apply to new Items only. An update never has a default written over a column it omitted. ## The preview step Uploading runs a dry run first. Nothing is written. You get three counts — to create, to update, rejected — and a list of every rejected row with the reason and the column at fault. **Download errors** gives you a CSV containing just the rejected rows, with your original columns plus an extra `Errors` column. Fix those rows, upload that file, and you are done — no need to re-upload the whole set. Confirming commits the import. The server re-validates everything and writes only the valid rows, then shows what actually happened. ## What every row is checked against * **Unknown columns** — every column must map to a field on this Collection. * **Required fields** — a blank required value rejects that row. * **Allowed values** — a value outside a field's Allowed Values list is rejected, unless that field has Allow new values switched on, in which case anything is accepted. * **Item ID** — must be unique in the Collection, and must match the Collection's Item ID mask if it generates Links from Item IDs. * **Cell format** — numbers as `123` or `123.45`; yes/no as `true`, `false`, `1` or `0`; dates as ISO `YYYY-MM-DD` only, so `31/12/2026` is rejected; list values separated by semicolons; and every row must have the same number of columns as the header. Bad rows are rejected one by one. The good rows in the same file still import, and a row with several problems reports all of them at once so you can fix it in a single pass. ## Columns that are ignored `image`, `created_at`, `updated_at` and internal columns are skipped on import. In particular, a CSV cannot set, change, or clear an Item's photo. One gotcha when you re-import a file QRtub exported: values beginning with `=`, `+`, `-`, `@` or a tab are exported with a leading apostrophe so spreadsheets do not read them as formulas, and the apostrophe is not stripped on the way back in. A negative number such as `-40` comes back as `'-40` and is rejected as an invalid number for that column. Delete the apostrophe before importing. ## Links for newly created Items A row that creates an Item also mints a Link for it, following the Collection's rule for new Items — exactly as if you had added the Item by hand. If a Link cannot be minted, the Item is still created and the row gets a warning telling you why, such as an Item ID that does not match the Collection's mask. ## Related * [Exporting Items to CSV](/import-export/exporting-items) * [Item ID](/items/item-id) * [Required Fields](/fields/required-fields) * [Allow New Values](/fields/allow-new-values) # QRtub Documentation Source: https://help.qrtub.com/index What QRtub does, why you can start anywhere, and where to find the page that answers your question. QRtub manages the QR-code layer between your physical items and the software systems that serve them. A QR code encodes a QRtub Link instead of a vendor's URL, so you can change where that code goes — or what it opens — without reprinting anything. ## Start anywhere A Collection, an Item, a Link and a Page do not require each other to exist. You can create Links and send them to a supplier before you know what they will point at, build a Page before any code opens it, or import real equipment data and print a box of spares in the same afternoon. Most systems make you finish the database before you can print; QRtub doesn't, and that changes how you sequence a rollout. The tutorial below is one workable path through that, not the required one. ## Start here * [Key Concepts](/key-concepts) — Collection, Item, Link, Page and Tag in a sentence each * [Creating Your First Link](/creating-your-first-link) — create a Collection, get a Link, connect it to an Item * [The Print-First Workflow](/print-first/overview) — printing codes before the Items exist ## Your data * [What Is a Collection?](/collections/overview) and [Creating a Collection](/collections/creating-a-collection) * [Core Fields vs. Custom Fields](/fields/core-vs-custom) — what data each Item carries * [What Is an Item?](/items/overview) * [Importing Items from CSV](/import-export/importing-items) ## Links and QR codes * [What a Link Is](/links/what-a-link-is) * [Choosing a Link Type](/links/choosing-a-link-type) — random, numbered, or custom * [Unallocated Links](/links/unallocated-links) — a real, printable Link with nothing attached yet * [Downloading QR Codes](/bulk-links/downloading-qr-codes) ## What a scan does * [Pages Overview](/pages/pages-overview) — one code, several destinations * [What Is a Destination?](/destinations/what-is-a-destination) * [Field Bindings & URL Templates](/destinations/field-bindings) — pre-fill another system with this Item's data ## Printing and rollout * [What Is a Tag?](/tags/what-is-a-tag) — stickers, plaques, signs, NFC tags * [Print Batches](/print-batches/overview) — tracking a production run * [Preparing Your Print Job](/suppliers/preparing-your-job) ## Use cases and integrations * Works with — [Mitti (formerly SafetyCulture)](/integrations/mitti/setup), [Google Forms](/integrations/google-forms) and [anything else with a URL](/integrations/overview); every recipe is a URL, not an API sync # Google Forms Source: https://help.qrtub.com/integrations/google-forms/overview How to use a Google Form as a Destination, and what the form's own sharing settings decide about who can submit it. ``` https://docs.google.com/forms/d/e/FORM_ID/viewform ``` Paste the form's own link in as the Destination. Get it from **Send** in the form, then the link tab. A shortened `forms.gle/...` link works the same way. ## Who can submit it By default, anyone with the link and no sign-in — which makes a Google Form one of the few Destinations a visitor or a member of the public can actually use. Two settings undo that, and both are worth checking before you produce a Batch: * A Workspace form **restricted to your organisation** asks an outsider to sign in, and a scan does not get them past it. * **Limit to 1 response** needs a Google account to enforce, so it turns an open form into a signed-in one. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) * [Pages Overview](/pages/pages-overview) — offering a form alongside other Destinations # Pre-filling a Google Form Source: https://help.qrtub.com/integrations/google-forms/prefill How to open a Google Form with answers already filled in from each Item's own fields, and which question types accept it. ``` https://docs.google.com/forms/d/e/FORM_ID/viewform?usp=pp_url&entry.1234567890={{item.itemId}} ``` Every Link in the Collection then opens the same form carrying its own Item's data, so whoever scans only answers what is actually new. ## Get the entry IDs from Google You cannot guess them and should not try. In the form, open the three-dot menu, choose **Get pre-filled link**, type anything into the questions you want pre-filled, then **Get link**. Google hands you a complete working URL — swap your placeholder values for bindings. `usp=pp_url` tells Google the URL carries pre-filled values. Each `entry.1234567890` is one question, and the number is unique to that question in that form. Several at once, joined by `&`: ``` ...&entry.1234567890={{item.itemId}}&entry.987654321={{item.location}} ``` ## Bind IDs, not sentences QRtub inserts the value character for character and does **no URL encoding**, so a value containing a space, `&`, `?` or `#` breaks the link. Bind an Item ID, a serial or a code — never a description or a note. If a binding cannot resolve, QRtub drops the Destination rather than opening a malformed form. ## What will not pre-fill **File upload** — Google blocks it. And for multiple choice, checkbox and dropdown the value must match one of the form's own options exactly, including capitalisation; a near miss silently pre-fills nothing. ## Related * [Google Forms](/integrations/google-forms/overview) * [Field Bindings & URL Templates](/destinations/field-bindings) # Google Maps Source: https://help.qrtub.com/integrations/google-maps How to open a location in Google Maps from a scan, including binding coordinates from each Item's own fields. ``` https://www.google.com/maps/search/?api=1&query=-33.8688,151.2093 ``` Replace the coordinates with bindings — `query={{item.latitude}},{{item.longitude}}` — and every Link opens the map at its own Item's position. For directions instead of a pin: ``` https://www.google.com/maps/dir/?api=1&destination={{item.latitude}},{{item.longitude}} ``` `api=1` is required in both. **No Google API key is needed** — these are Maps URLs, not the Maps API. ## Bind coordinates, not place names `query=` accepts a place name as well, but a name has spaces in it, and spaces have to arrive as `+` or `%20`. QRtub does no URL encoding, so a bound place name breaks the link. Coordinates have no spaces, so they are safe. Store latitude and longitude as their own fields and bind those. ## Related * [Field Bindings & URL Templates](/destinations/field-bindings) * [What Is a Destination?](/destinations/what-is-a-destination) # Google Drive, Docs and Sheets Source: https://help.qrtub.com/integrations/google-workspace How to use a Drive file, folder, Doc, Sheet or Slides deck as a Destination, and what the file's General access setting decides about who can open it. ``` https://docs.google.com/document/d/FILE_ID/edit ``` Do not build this by hand. Open the file, choose **Share → Copy link**, and paste that in as the Destination. The same applies to a Sheet, a Slides deck, and to any file or folder in Drive. Swapping `/edit` for `/preview` opens a Doc read-only, without the editing toolbar — usually what you want on a tag. ## Who can open it The file's **General access** setting decides this, and it is the only thing that matters here: * **Restricted** — only named people, and the default for a new file. A scan does not bypass it: anyone else gets Google's request-access screen, which is the file behaving correctly. * **Anyone with the link** — what you set if people outside your organisation should be able to open it. Set the role to **Viewer** unless you genuinely want scanners editing the file. **Test in a private window before you produce a Batch.** Signed in as the file's owner, everything opens — so a Restricted file looks fine right up until someone else scans it. The access rule is doing its job; you just want to know which rule is set before five hundred tags carry the code. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) * [Microsoft 365](/integrations/microsoft-365) — the same job, the same trap # Jotform Source: https://help.qrtub.com/integrations/jotform How to use a Jotform form as a Destination, and when to reach for it instead of Google Forms. ``` https://form.jotform.com/FORM_ID ``` Take the form's own link from **Publish → Quick Share** and paste it in as the Destination. Public and submittable with no account, like Google Forms. ## When Jotform rather than Google Forms Reach for it when the form has to do something a Google Form cannot: conditional questions, signatures, payments, file uploads with real limits, or a layout that has to look like your organisation produced it. For a plain three-question fault report, either will do, and the one your team already uses is the right answer. ## Related * [Google Forms](/integrations/google-forms/overview) * [What Is a Destination?](/destinations/what-is-a-destination) # MaintainX Source: https://help.qrtub.com/integrations/maintainx How to point a Link at a MaintainX request portal so anyone can raise a maintenance request without a MaintainX account. Get the link from the request portal itself — MaintainX generates it when you create the portal, and offers it as both a web link and a QR code. Paste the web link in as the Destination. ## Why the request portal is the useful one A request portal lets **someone with no MaintainX account** submit a maintenance request; it lands in your Requests inbox like any other. That makes it one of the few Destinations a tenant, a contractor or a member of the public can actually use. MaintainX can also generate **portal links for a specific asset or location**, so a tag on a particular unit can raise a request already attached to it. ## Their QR codes and QRtub's MaintainX mints its own QR codes for assets and portals, and they work well — they are simply fixed at the moment they are made. A QRtub Link in front of one can be re-pointed later: to a different portal, to a different asset after a replacement, or to something else entirely, without producing the tag again. That is the whole reason to put a QRtub Link between the tag and MaintainX rather than printing theirs directly. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) * [Mitti](/integrations/mitti/setup) — the same pattern, a different platform # Microsoft 365 Source: https://help.qrtub.com/integrations/microsoft-365 How to use a SharePoint or OneDrive file or folder as a Destination, and why the sharing scope usually decides whether a scan works. Open the file in SharePoint or OneDrive, choose **Share → Copy link**, and paste it in as the Destination. The link already carries everything it needs; there is nothing to construct. ## Your tenant's sharing rules still apply The share dialog offers something like **Anyone with the link**, **People in *your organisation***, **People with existing access** and **Specific people**. Whichever you pick is what a scan gets — a QRtub Link carries the address, not permission, so the file stays exactly as protected as it is today. Two consequences worth planning around: * **Your own staff, signed in** — works well, and the link survives the file moving within the site. * **Contractors, visitors, the public** — they need **Anyone with the link**, and many tenants switch that off centrally. That is a deliberate policy, not an obstacle to route around: if IT has blocked anonymous links, publish the public-facing version somewhere you control and keep the governed copy here. This is the practical difference from Google Drive, where you can usually change a file's access yourself. ## Related * [Google Drive, Docs and Sheets](/integrations/google-workspace) — the same job, fewer obstacles * [What Is a Destination?](/destinations/what-is-a-destination) # What a Scan Can Open in Mitti Source: https://help.qrtub.com/integrations/mitti/entities Every Mitti destination a Link can point at, what each one is useful for, and which of them a person without a Mitti account can open. ## What a scan can open in Mitti Starting an inspection is the common case, but a Link can point at any of these. Pick by what the person holding the phone actually needs. | What it opens | A concrete use | Who can open it | | ------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------- | | **A new inspection** | The pre-start checklist for this excavator | Mitti user, template access, app | | **A new inspection, pre-filled** | Serial, site and asset number already answered before the operator starts | Mitti user, template access, app | | **An existing inspection** | Resume the half-finished handover form on the crane | Mitti user | | **One question inside an inspection** | The plate on the switchboard opens its own question, not page 1 of 90 | Mitti user | | **The latest report** | A hire client scans the plate and reads the last check before signing for it | Mitti user, report access | | **A training course** | The plate on the boom lift opens its operating course before anyone gets in | Mitti user | | **An asset profile** | Service history and open actions for this pump | Mitti user, **mobile app** | | **A file or folder** | The current SOP for this machine, always the latest version | Mitti user, file access, **mobile app** | | **Issue reporting** | A visitor or a delivery driver reports a damaged bollard | **Anyone — no account** | **Mitti's own access rules still apply, and that is the point.** Issue reporting is open by design; everything else in that table asks for a Mitti login, and asset profiles and files also want the mobile app. A code on a machine gives nobody a way past that — a stranger who scans meets Mitti's sign-in, because protecting those records is Mitti's job and it is still doing it. So a tag for a mixed audience is a design decision, not a risk. Decide what the public should be offered, put that on a QRtub [Page](/pages/pages-overview), and list the Mitti destinations alongside it. Your crew taps straight through; everyone else gets what you chose to publish. One tag, both audiences, and nothing exposed that was not already. ### An existing inspection **Mobile:** `iauditor://audit/` **Web:** `https://app.mitti.com/inspection/` **Use it for:** a long handover or commissioning form that gets finished over several visits. The tag on the unit reopens the same inspection instead of starting a new one. ### One question, or one page, inside an inspection **Web:** `https://app.mitti.com/inspection/?item=` **Web:** `https://app.mitti.com/inspection/?page=` **Mobile:** `iauditor://audit//item/` **Use it for:** one long inspection covering a whole plant room, with a tag on each item of equipment that opens its own question. Nobody scrolls, and nobody answers the wrong row. ### The latest inspection report **Web:** `https://app.mitti.com/report/audit/` **With a URL template:** ``` https://app.mitti.com/report/audit/{{item.inspectionID}} ``` Store the current inspection ID in each Item's `inspectionID` field, and every tag resolves to its own item's most recent report. **Use it for:** proving a check happened. A client or an auditor scans the plate and reads the last inspection without anyone fetching a file for them. ### A training course **Web:** `https://app.mitti.com/training/learn/course/` **Mobile:** `iauditor://training/learn/course/` **Use it for:** the induction or operating course for the machine the tag is on — reachable at the machine, at the moment somebody is about to use it, rather than in an email from six months ago. ### An asset profile **Mobile:** `iauditor://asset/profile/` **Web:** `https://app.mitti.com/assets/` **Use it for:** history and open actions. A fitter scanning a pump sees what has been done to it and what is outstanding. ### A file or folder **Web:** `https://app.mitti.com/documents/document/` **Use it for:** the manual, SOP or safe-work method that has to be the current version. Mitti serves the latest one, so re-issuing the document never means re-producing the tag. ### Issue reporting Issue QR codes are made in Mitti under **Issues → QR codes**, and they are the one Mitti destination a stranger can use. They have no URL pattern to build — create the code, copy its link, and use that link as your Destination. **Use it for:** the fault-reporting button on anything the public or a visitor can reach — a council bin, a bollard, a lift lobby, a hire item on a customer site. Because there is no URL pattern, an issue link cannot be built per Item with [field bindings](/destinations/field-bindings) the way the others can. Every Item pointed at one issue code shares it, unless you create a separate code in Mitti for each site or asset. Issue codes can be pre-filled in Mitti with a category, site or asset when you create them. ## Which ones bindings can build for you This is the difference that decides how much work a fleet takes. * **Templates, inspections, questions, reports, courses, assets and files** all have a URL with an ID in it. So you write one URL template with a binding — `{{item.assetID}}` — and every Link in the Collection resolves to its own record. One rule, whole fleet. * **Issue codes** have no pattern. You paste a link, one at a time. ## Related * [Setting Up Mitti](/integrations/mitti/setup) * [Pre-filling a Mitti Inspection](/integrations/mitti/prefilling) * [Field Bindings & URL Templates](/destinations/field-bindings) # Pre-filling a Mitti Inspection Source: https://help.qrtub.com/integrations/mitti/prefilling Carrying each Item's own data into an inspection so the operator only answers what is new. ## Advanced: Pre-Fill Inspection Questions Mitti allows you to pre-fill specific inspection questions using question item IDs. ### Mobile App Pre-Fill Format ``` iauditor://template/new_audit/?= ``` **Example with QRtub URL Templates:** ``` iauditor://template/new_audit/template_fcbc86fd41a74180921347e4be53bdf2?8f2f287e-be6e-470c-a2e2-a0fd8ab966ae={{item.assetID}} ``` Where: * `template_fcbc86fd41a74180921347e4be53bdf2` is your Mitti template ID * `8f2f287e-be6e-470c-a2e2-a0fd8ab966ae` is the question item ID in your template * `{{item.assetID}}` is the QRtub field binding — replaced with that Item's own asset ID before the link opens **At volume:** Configure this URL once for 500 pieces of equipment. Each scan substitutes that Item's own asset ID into the link, and Mitti reads the parameter and pre-fills the matching question. No manual setup per Item. ### Pre-Fill Multiple Questions Use `&` to pre-fill multiple questions: ``` iauditor://template/new_audit/?=&= ``` **Example:** ``` iauditor://template/new_audit/template_fcbc86fd41a74180921347e4be53bdf2?8f2f287e={{item.assetID}}&a2e2a0fd={{item.location}} ``` **Important notes:** * You need the specific **question item ID** from your Mitti template (not arbitrary parameter names) * To get question item IDs, see [Mitti's entity ID guide](https://help.mitti.com/en-US/000076/) * QRtub inserts field values exactly as stored and never URL-encodes them. A value containing a space, `&` or `#` will break the deep link — store it pre-encoded in the Item field * Very long deep links may not work consistently ## Related * [Setting Up Mitti](/integrations/mitti/setup) * [What a Scan Can Open in Mitti](/integrations/mitti/entities) * [Field Bindings & URL Templates](/destinations/field-bindings) # Setting Up Mitti Source: https://help.qrtub.com/integrations/mitti/setup Connecting a Link to Mitti with deep links, where to find a template ID, and the three naming eras of the product. Point a QRtub Link at a Mitti destination and a scan lands straight on the right record — the inspection for this machine, its last report, its asset history, or a form a visitor can use without a Mitti account. ## If you know it as SafetyCulture or iAuditor Same product, three names. It launched as **iAuditor**, was renamed **SafetyCulture**, and became **Mitti** in August 2026. SafetyCulture remains the company; Mitti is the platform. Nothing you have already set up stops working: * The mobile app kept its identifiers, so the **`iauditor://` deep link scheme still works**. You will see it throughout this page, and it is correct — not a leftover. * **`app.safetyculture.com` URLs still resolve.** Examples below use `app.mitti.com`, but you do not need to go back and change anything. ## Overview Mitti (formerly SafetyCulture) is a workplace operations platform. Used with QRtub, you can: * Open a specific inspection template by scanning the equipment it belongs to * Carry each Item's own data into the link, which Mitti uses to pre-fill answers * Offer several Mitti destinations on one code, so whoever scans picks what they came for * Reach destinations Mitti has a URL for but does not make a QR code for — a training course, a report, or one question inside a long inspection * Change which record a code opens without producing the tag again, including if you switch platforms later ## Integration Method QRtub connects to Mitti using **deep links** — URLs that open Mitti directly at a specific inspection, template or report. No data is exchanged between the two systems; QRtub builds the URL and Mitti handles the rest. Mitti supports two deep link formats: * **Mobile app** (`iauditor://`) — opens the Mitti app. The scheme still carries the old name * **Web app** (`https://app.mitti.com/`) — opens in a browser. `app.mitti.com` also works ## Getting Your Template ID Before setting up deep links, you'll need your Mitti Template ID: 1. Open the Mitti web app 2. Navigate to your inspection template 3. Copy the Template ID from the URL 4. Example: `template_fcbc86fd41a74180921347e4be53bdf2` See [Mitti's guide on getting entity IDs](https://help.mitti.com/en-US/000076/) for detailed instructions. ## Basic Setup: Start Inspection ### Mobile App Deep Link In your Item's Page, add a new Destination: **Destination Name:** Start Inspection **Destination URL:** `iauditor://template/new_audit/` **Example:** ``` iauditor://template/new_audit/template_fcbc86fd41a74180921347e4be53bdf2 ``` ### Web App Deep Link Alternatively, use a web app deep link for users who prefer desktop/browser access: **Destination Name:** Start Inspection (Web) **Destination URL:** `https://app.mitti.com/inspection/new?templateId=` **Example:** ``` https://app.mitti.com/inspection/new?templateId=template_fcbc86fd41a74180921347e4be53bdf2 ``` ### Using QRtub URL Templates Use QRtub's URL Template feature to automatically insert template IDs from your Item data: **Destination URL:** `iauditor://template/new_audit/{{item.templateID}}` **Why this matters at volume:** Configure the Destination once with a template placeholder. Each Item in your Collection can have a different `templateID` field value—some use the forklift inspection template, others use the excavator template. One Destination configuration serves all equipment types, with each QR code routing to its specific inspection template automatically. This allows different Items to use different Mitti templates based on their Item data—no manual configuration per Item. ## Related * [What a Scan Can Open in Mitti](/integrations/mitti/entities) * [Pre-filling a Mitti Inspection](/integrations/mitti/prefilling) * [Fallbacks and Troubleshooting](/integrations/mitti/troubleshooting) # Fallbacks and Troubleshooting Source: https://help.qrtub.com/integrations/mitti/troubleshooting What to set when the Mitti app is not installed, and what to check when a scan does not land where you expect. ## App Not Installed? Set a Fallback URL `iauditor://` deep links only work if Mitti is installed on the device. If someone scans and doesn't have the app, the link does nothing. QRtub handles this automatically. When you enter an `iauditor://` URL as a Destination, an amber notice appears in the editor prompting you to configure a fallback. **Recommended setup:** | Field | Value | | -------------------------- | --------------------------------------------------------------------- | | App link (Destination URL) | `iauditor://template/new_audit/{{item.templateID}}` | | Fallback URL | `https://app.mitti.com/inspection/new?templateId={{item.templateID}}` | **What happens at scan time:** * Mitti installed → app opens directly to the inspection template * Mitti not installed → after 2.5 seconds, QRtub redirects to the web version The Fallback URL supports `{{item.field}}` bindings, so you configure it once and it adapts to each Item automatically — just like the app link itself. You can also set a **Fallback Message** instead of a URL if there's no web equivalent (e.g. "Please install Mitti to access this inspection template"). See [App Links & Fallback URLs](/destinations/app-links) for full details on how fallbacks work. ## Troubleshooting **Mobile app doesn't open:** * Ensure Mitti app is installed on the device * Verify Template ID format is correct * Check that the user has access to the template in Mitti **Web link doesn't work:** * Verify user is logged into Mitti web app * Check that the user has permission to access the entity (template, inspection, asset) * Confirm the entity ID is correct **Data not pre-filling:** * You need the specific **question item ID** from your Mitti template (not arbitrary field names) * Ensure Item fields in QRtub contain data * Test that URL encoding is correct for special characters * Verify deep link isn't too long (keep it under \~2000 characters) **Users need access:** Deep links only work if users have permission to access the relevant entities in Mitti. Ensure your team has appropriate access before you produce a Batch. ## Resources * [Mitti deep link documentation](https://help.mitti.com/en-US/000149/) * [Get Mitti entity IDs](https://help.mitti.com/en-US/000076/) * [Create issue QR codes](https://help.mitti.com/000165) — the one Mitti destination that needs no account * [Create asset profile QR codes](https://help.mitti.com/002882) * [Create QR codes for files and folders](https://help.mitti.com/005378) — note the access requirements * [Share inspection QR codes](https://help.mitti.com/002257) * [App Links & Fallback URLs](/destinations/app-links) * [Pages Overview](/pages/pages-overview) * [Key Concepts](/key-concepts) ## Related * [Setting Up Mitti](/integrations/mitti/setup) * [App Links & Fallback URLs](/destinations/app-links) # Notion Source: https://help.qrtub.com/integrations/notion How to use a Notion page as a Destination, and the one toggle that decides whether anyone outside your workspace can read it. ``` https://www.notion.so/Page-Title-PAGE_ID ``` Use **Share → Copy link** on the page. ## Publishing is the decision A Notion link is workspace-only by default, and a scan does not change that — someone outside your workspace is asked to sign in, which is Notion protecting your content rather than a fault in the tag. **Share → Publish** (sometimes shown as *Share to web*) makes the page readable by anyone with the link. That is what a tag needs — and it is a real decision, not a formality: a published Notion page is public to anyone who finds the URL, and sub-pages can be included. So publish pages written to be read by outsiders. Do not publish an internal page just to make a tag work. ## Sub-pages come along If the published page links to child pages, those become reachable too. Worth a look before you publish a page that sits high in a workspace. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) * [Pages Overview](/pages/pages-overview) — if you want branding around it, use a QRtub Page instead # Works with QRtub Source: https://help.qrtub.com/integrations/overview Every platform with a recipe written up. QRtub points a code at a URL, so it works with anything that has one. There is no API key, no OAuth and nothing to install on the other side. Inspections, reports, asset profiles, files and issue reporting. A maintenance request, from someone with no MaintainX account. An online booking form, hosted publicly by ServiceM8. A form anyone can submit without signing in. A form, when you need conditions, signatures or payments. A Doc, Sheet, Slides deck, file or folder. A SharePoint or OneDrive file or folder. A published Notion page. A location, from each Item's own coordinates. A video, at a particular second. A conversation with the message already written. # ServiceM8 Source: https://help.qrtub.com/integrations/servicem8 How to point a Link at a ServiceM8 online booking form, and the two limits that decide where this works. Get the link from **Settings → Online Booking**, or from **Settings → Self-Serve Online Bookings** if you have several forms. ServiceM8 hosts the form, so the link works for anyone — no account, no app. A tag on a hot water system, a switchboard or a site sign that books a service call is about as direct as this gets. ## Two limits worth knowing before you produce anything **There is no per-asset URL.** You point at a *booking form*, not at a record. So the useful split is one form per service type — and that means the Destination varies by what the tag is on, not by which unit it is. There is nothing per-Item to bind. **SMS booking links are single-use.** ServiceM8 can text a customer a link to pick a time for an existing job, and that link is tied to that job and that booking. It is not something to print. If one ends up on a tag it will work once and then be wrong forever. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) * [Collections Overview](/collections/overview) — one Collection per service type is usually the shape # WhatsApp Source: https://help.qrtub.com/integrations/whatsapp How to open a WhatsApp conversation from a scan with the message already written, and the exact number format required. ``` https://wa.me/61400000000?text=Fault%20on%20PLANT-0412 ``` Opens a WhatsApp chat to that number with the message already typed. The person scanning still presses send, so nothing is sent without them. ## The number format is strict Digits only, with the country code, and nothing else: * **No** `+`, no spaces, no brackets, no dashes * **No leading zero** — an Australian `0400 000 000` becomes `61400000000` * **No** `00` international prefix either; the country code alone is enough A wrongly formatted number does not error. It opens WhatsApp on a chat to nobody. ## Encode the words, bind only the ID `text=` has to be URL-encoded, and QRtub does no encoding. So write the static part already encoded, and bind only a value with no spaces in it: ``` https://wa.me/61400000000?text=Fault%20on%20{{item.itemId}} ``` `%20` is a space. Never bind a description or a note — the first space breaks the link. ## Related * [Field Bindings & URL Templates](/destinations/field-bindings) * [What Is a Destination?](/destinations/what-is-a-destination) # YouTube Source: https://help.qrtub.com/integrations/youtube How to open a video from a scan, and how to start it at a particular moment. ``` https://youtu.be/VIDEO_ID?t=90 ``` `?t=90` starts the video 90 seconds in. Drop it to start from the beginning. Use **Share** on the video to get the short link — it already contains the ID. Free hosting, no app to install, and the person scanning needs no account. For a machine that needs a start-up procedure or a lockout sequence explained, a video at the right second is often better than a document. ## Unlisted, not private * **Unlisted** is what a tag wants — anyone with the link can watch, and it stays out of search and off your channel page. * **Private** stays private. It is limited to named Google accounts, and a code on a machine does not change that. ## Related * [What Is a Destination?](/destinations/what-is-a-destination) * [Pages Overview](/pages/pages-overview) — a video alongside other Destinations # Duplicating an Item Source: https://help.qrtub.com/items/duplicating What the Duplicate action copies and what it deliberately does not — the Item ID prompt, the new Link, and the page override that stays behind Duplicating an Item creates a second Item in the same Collection with the same field values. It is the fastest way to add the tenth near-identical extinguisher or hire unit. Open the items table, use the menu at the end of an Item's row, and choose **Duplicate**. To copy several at once, select the Items and choose **Duplicate Selected Items** from the bulk actions menu. ## What carries over Everything you filled in comes across: Description, Tags, the photo, every custom field, and the Item's Destination settings. The Name comes across with `(Copy)` appended, so "Generator" becomes "Generator (Copy)". An Item with no name at all produces a copy called "Copy". One subtlety: the copy is created like any other new Item, so any Collection-level field **defaults** apply to fields that were blank on the source. A field left empty on the original can arrive filled in on the copy. ## What does not carry over **The Item ID.** Item IDs are unique within a Collection, so the copy cannot inherit one. If the source Item has an Item ID, you are prompted for a new one before the copy is created — the prompt shows the source's value as a placeholder. If the value you type is rejected, because it is already in use or does not match the Collection's Item ID mask, you are asked again with the reason shown. Canceling skips that Item; in a bulk duplicate the remaining Items still proceed. If the source has no Item ID, you get a simple confirmation instead and the copy is created without one. **The source Item's page override.** Per-Item page overrides are attached to a specific Item, and the copy is a new Item, so it starts on the Collection's base page template. If the original had its own tweaked page, re-apply them on the copy. **Internal values.** The copy gets its own internal ID and its own created and updated timestamps. Nothing is shared with the original — editing one afterwards never affects the other. ## The copy gets its own Link Because the copy is a genuinely new Item, the Collection's rule for new Items runs for it. In random-link mode the copy gets a fresh random Link. In Item-ID mode the Link is built from the Item ID you just typed. If a copy somehow ends up with no Item ID in Item-ID mode, it is created successfully but without a Link, and you are told to assign an Item ID to generate one. Duplicates are created one at a time. If one fails, the reason is shown and the rest continue. ## Related * [Item ID](/items/item-id) * [What Is an Item?](/items/overview) * [Per-Item Page Overrides](/pages/page-overrides) # Item ID Source: https://help.qrtub.com/items/item-id The identifier you control on each Item: unique within its Collection, optional, and the value ID-based Links are built from Item ID is your own identifier for an Item — the plant number, asset number, or tag number your business already uses. Unlike Name, it is unique within the Collection, which makes it the field you use to tell two similar Items apart. ## Uniqueness and blank values No two Items in the same Collection can hold the same Item ID. The constraint is per Collection, so "EXC-203" in Heavy Equipment and "EXC-203" in Hire Fleet are fine — the same value twice in one Collection is rejected. Item ID is optional. Values are trimmed before they are stored, and a blank or whitespace-only value is stored as no value at all, so any number of Items in a Collection can have no Item ID without colliding with each other. Trimming also means `" EXC-203 "` and `"EXC-203"` are the same Item ID, not two different ones. ## Where Item ID appears * In the items table, and as the subtitle under an Item's name when another Item references it through a reference field. * In the search box of the item picker inside the item form, alongside Name and Description. * In bindings, as `{{item.item_id}}` — usable in a Destination URL such as `https://example.com/items/{{item.item_id}}`. Bindings are inserted exactly as stored with no URL encoding, so keep Item IDs free of spaces and `&` if you build URLs from them. ## Item ID and ID-based Links If the Collection generates Links from Item IDs, the Item ID *is* the Link's slug. The Collection defines a mask — a prefix, a digit count, and an optional suffix, such as `CRA####TL` — and an Item with the Item ID `CRA0042TL` gets the Link `qrtub.com/CRA0042TL`. That mode adds real rules to this field: * The Item ID must match the mask. The check runs in the item form, in the API, and on CSV import, and a value like `CRA42TL` is rejected for having the wrong number of digits. * An Item saved with no Item ID is created successfully but gets no Link, because there is nothing to build the slug from. You will see a message saying so. * If that slug already exists as an unassigned Link — a code you pre-printed — the existing Link is adopted rather than duplicated. If it is already attached to a different Item, the save is rejected and you are told to pick an unused number. None of this applies in the other link-generation modes, where Item ID is simply an identifier you keep for your own reference. ## Two behaviors that surprise people **Duplicating an Item never copies its Item ID**, because the copy would collide on the uniqueness constraint. You are prompted for a new one instead. **On CSV import, duplicate Item IDs are caught in the preview**, before anything is written — both a value already used by another Item in the Collection and the same value appearing twice in the file. Those rows are rejected individually; the rest of the file still imports. ## Related * [What Is an Item?](/items/overview) * [Name and Description](/items/name-and-description) * [Duplicating an Item](/items/duplicating) * [Importing Items from CSV](/import-export/importing-items) # Keywords Source: https://help.qrtub.com/items/keywords The core Keywords field: entering multiple values, why the chips are colored, and the comma-versus-semicolon difference between the form and CSV Keywords is the core field that holds a list of values rather than a single one. It is where cross-cutting labels go — `site-a`, `hired-in`, `needs-service` — the kind of thing you would not create a dedicated field for. ## Entering keywords By default Keywords is a plain text box and you type your values separated by commas: ```text theme={null} site-a, hired-in, needs-service ``` Each value is trimmed, empty entries are dropped, and duplicates are removed, so `site-a, , site-a` is stored as the single keyword `site-a`. ## Turning Keywords into a picker Add Allowed Values to the Keywords field in the Collection's Fields tab and the text box becomes a multi-select list of those options. This is what you want once a team is sharing a Collection — it stops `site-a`, `Site A` and `sitea` from all existing at once. Keywords ships with **Allow new values** turned on, so even as a picker it keeps an "Add new\..." box in the dropdown: someone can still add a value that is not on the list, and it is registered for everyone to reuse. Turn Allow new values off and both the item form and CSV import reject any value outside the list. ## Why the chips are colored Chip colors come from the Allowed Values list, not from the Item. Each allowed value can be given a color, and that color is used wherever the value is rendered — the items table and the Page someone sees after scanning. Configure the color once on the field and it applies everywhere. A value that was typed freely and has no matching allowed value simply renders with no color. That is the usual reason a chip looks plain next to colored siblings. On a Page, both the Keywords section and the ItemHeader section's chips default to the `{{item.tags}}` binding, so keywords show up without you configuring anything. ## Keywords in CSV files Keywords use a **semicolon** in CSV, not a comma — commas separate columns: ```text theme={null} name,tags Excavator 203,site-a; hired-in ``` Exports join the values with `; `, and imports accept them with or without the space after the semicolon. A cell with no semicolon is imported as a single-value list. ## Related * [What Is an Item?](/items/overview) * [Allowed Values](/fields/allowed-values) * [Allow New Values](/fields/allow-new-values) * [Importing Items from CSV](/import-export/importing-items) The field is labelled **Keywords**, but its binding keeps the stable code name — write `{{item.tags}}`, not `{{item.keywords}}`. Renaming a user-facing label never changes a binding; see [Renaming a Field](/fields/renaming-a-field). # Name and Description Source: https://help.qrtub.com/items/name-and-description The two free-text core fields on every Item: what Name is used for, where Description shows up, and why neither one has to be unique Name and Description are the two free-text core fields every Item ships with. Both accept any text, neither has to be unique, and both live in fixed database columns that can be relabeled but never renamed. ## Name Name is the Item's primary label — it is what you see in the items table, in the item picker, and in the preview another Item shows when it references this one. On a Page, the ItemHeader section's title defaults to the `{{item.name}}` binding, so an Item's name is usually the heading someone sees after scanning its code. Name is **not required by default**. You can mark it Required in the Collection's Fields tab, at which point it is enforced when an Item is created, when it is edited, and on CSV import. Names are not unique. Two Items in the same Collection can both be called "Generator", and QRtub will not warn you. If you need to tell same-named Items apart, that is what [Item ID](/items/item-id) is for — it is unique within the Collection. One small behavior worth knowing: duplicating an Item appends `(Copy)` to the name, so "Generator" becomes "Generator (Copy)". If the source Item has no name at all, the copy is simply called "Copy". ## Description Description is the longer free-text field — the place for a sentence or a paragraph rather than a label. It is optional unless you mark it Required. Description earns its keep on Pages. The Text section's content defaults to `{{item.description}}`, and several of the starter page templates already bind it, so dropping a Text section onto a page shows the Item's description without you typing a binding. The item picker inside the item form also searches Description alongside Name and Item ID. ## Relabeling, requiring, and turning them off Both fields are configured on the Collection, in its Fields tab. You can change the label a field shows in forms and as its CSV column header, tick Required, or turn the field off. Because these are core fields, they can only be **disabled**, never deleted — the stored values are untouched and come back if you re-enable the field. Note that a disabled core field still resolves in Page bindings: turning Description off hides it from the item form and the items table, but `{{item.description}}` on a Page keeps rendering whatever was already stored. ## Related * [What Is an Item?](/items/overview) * [Item ID](/items/item-id) * [Duplicating an Item](/items/duplicating) # What Is an Item? Source: https://help.qrtub.com/items/overview The individual record a Collection tracks — its four core fields, its custom fields, its photo, and how it connects to Links and Pages An Item is one record inside a Collection: one excavator, one fire extinguisher, one meeting room, one product. Items are what you actually manage — the things your QR codes point at. Every Item belongs to exactly one Collection, and the Collection decides what fields that Item has. Add a "Service Hours" field to the Collection and every Item in it gains that field. ## What every Item is made of Four **core fields** ship on every Item and cannot be removed: **Name**, **Item ID**, **Description** and **Tags**. They live in fixed database columns. You can relabel them, mark them required, or turn them off in the Collection's Fields tab, but their underlying keys never change — `name`, `item_id`, `description`, `tags`. Everything else is a **custom field** the Collection defines: a serial number, an inspection date, a status, a reference to the site the Item sits on. Custom fields are stored against a stable internal identifier, which is what makes renaming one safe later. ## The Item photo Every Item can also carry one photo. It is a system field, not part of the Collection's field configuration, so it cannot be renamed, disabled, or duplicated as a second image slot. Upload it from the item form. That photo appears in three places: the items table, the Item's Page wherever the `{{item.image}}` binding is used, and the preview shown when another Item references this one (a reference field displays the referenced Item's photo, name, and Item ID rather than a raw identifier). The photo is the one field CSV does not carry. It is excluded from every CSV export and ignored on import, so a CSV round-trip never changes or clears it. ## How an Item relates to Links and Pages An Item is not a Link. A Link is the QRtub-managed URL a QR code encodes; the Item is the record it resolves to. An Item can have no Links, one Link, or several. Depending on the Collection's link-generation setting, a Link is minted automatically the moment the Item is created. When a Link pointing at this Item is scanned, the Collection's page template renders using this Item's values — `{{item.name}}`, `{{item.status}}`, and so on. Two things to know about those bindings: * Values are inserted **exactly as stored**, with no URL encoding. A field containing a space, `&`, `?` or `#` will break a Destination URL built from it. * Collection fields use the `collection.` prefix — `{{collection.name}}` returns the Collection's name. Deleting an Item does not delete its Links. They are released back to your unassigned Links, so codes already printed and stuck to physical things keep resolving. ## Related * [Name and Description](/items/name-and-description) * [Item ID](/items/item-id) * [Keywords](/items/keywords) * [What Is a Collection?](/collections/overview) # Key Concepts Source: https://help.qrtub.com/key-concepts One or two sentences each on Collection, Item, Link, Page and Tag, and which page owns the full explanation of each. QRtub has five nouns. None of them require each other to exist — a Link can be printed before any Item exists, and a Page can be built before any code opens it — so this page defines each one and points to the page that owns it. ## Collection A Collection groups Items that share one field schema, one link-generation rule, one scan behavior, and one page template. It belongs to a team, and every Item belongs to exactly one Collection. In URL templates and conditions, the namespace for Collection values is still `collection.` — write `{{collection.name}}`, because `collection.name` returns an empty string with no error. See [What Is a Collection?](/collections/overview). ## Item An Item is the individual record a Collection tracks: one machine, one room, one product, one extinguisher. What data it holds is decided by its Collection's fields, and it can carry one or more Links. See [What Is an Item?](/items/overview) and [Core Fields vs. Custom Fields](/fields/core-vs-custom). ## Link A Link is a QRtub-managed URL, like `qrtub.com/r/x5fgd`, that resolves to a destination. A QR code is one way to encode it — an NFC tag or a typed address work the same way. Links belong to the team rather than to a Collection, so any Link can be assigned to any Item the team owns, or to nothing at all. See [What a Link Is](/links/what-a-link-is). ## Page A Page is the mobile screen a Link can open, holding one or more Destinations for the person scanning to choose from, and built in the Page Editor. A Link that skips the Page and redirects straight to a single Destination is in Direct Mode; a Link that opens a Page is in Page Mode. See [Pages Overview](/pages/pages-overview) and [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode). ## Tags A Tag is the physical thing the QR code lives on — a vinyl sticker, an engraved plaque, a sign, an NFC chip — with a lifecycle of its own, often longer than the Item it is attached to. QRtub tracks production runs as print batches; it does not keep a per-code record of material, cost, or installation location. See [What Is a Tag?](/tags/what-is-a-tag) and [Print Batches](/print-batches/overview). ## Related * [Creating Your First Link](/creating-your-first-link) — these five in one worked example * [The Print-First Workflow](/print-first/overview) — why printing before the data exists is normal here * [What Is a Destination?](/destinations/what-is-a-destination) — where a scan actually ends up # Choosing a Link Type Source: https://help.qrtub.com/links/choosing-a-link-type Random, Numbered and Custom Links compared side by side — who picks the slug, how many you can create at once, and which one fits a print run, a fleet numbering scheme or a memorable address QRtub has three ways to create a Link, and they differ in exactly one thing: who chooses the slug. Random slugs are drawn by QRtub, numbered slugs come from a pattern you reserve, and custom slugs are typed by you. Everything downstream — destinations, Items, Pages, printing — works identically whichever you pick. Pick **Random** unless you have a reason not to. Pick **Numbered** when the tag needs a human-readable number that matches an asset scheme. Pick **Custom** when a person will read the address out loud or type it from memory. ## The three types side by side | | Random | Numbered | Custom | | --------------------------- | ---------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------- | | Who picks the slug | QRtub | You define the pattern; QRtub fills in the number | You, exactly | | Example address | `qrtub.com/r/x5fgd` | `qrtub.com/cra0042tl` | `qrtub.com/boardroom` | | Slug shape | 5 characters, letters and digits | `prefix` + zero-padded number + `suffix` | 3–50 characters, lowercase letters, digits, `-` and `_` | | Typing it by hand | Must match lowercase exactly | Case doesn't matter | Case doesn't matter | | Setup needed | None | Claim a pattern first (QRtub can claim it for you on first use) | None | | How many at once | Up to 100 per request in the create form | Up to 1,000 numbers in one range request | One at a time | | Can fail because it's taken | No — QRtub retries | Yes, if another team already owns the pattern | Yes, if the slug is in use or reserved | | Included in | Every plan | Professional and Scale | Every plan | ## When Random is right Anything that is scanned rather than read. Codes on a sheet of stickers, spares in a drawer, a batch going out for print where nobody cares what the address says. It is the fastest route — nothing to configure, nothing that can collide, and it is the mode QRtub uses when a new Collection mints a Link automatically for each new Item. The trade-off is that a random slug carries no meaning and is unforgiving to type: it is matched case-sensitively, so someone entering it by hand has to get it exactly right. ## When Numbered is right When the physical tag already has a number, or should have one. A plate that reads `CRA0042TL` and resolves at `qrtub.com/cra0042tl` gives your crew one identifier instead of two — no mapping back to a spreadsheet, nothing to mistype twice. It is also the only type that mints in real bulk: one range request can create up to a thousand sequential codes. The cost is that a pattern is a commitment. A prefix, digit count and suffix combination is claimed exclusively, and once Links exist against it you cannot delete the pattern without deleting those Links first. ## When Custom is right When a human is the interface. A meeting-room sign, a poster, a business card, anything where someone might say "go to qrtub.com/boardroom". Custom slugs are the only type you fully control, and the only type validated against a reserved-word list — QRtub blocks slugs that would collide with its own routes and brand terms. They are also the slowest: one at a time, each one checked for availability, so they are a poor fit for a print run of five hundred. ## Mixing types is normal A team routinely runs all three: numbered plates on the equipment fleet, random codes for the spares box, a handful of custom slugs for the front-of-house signage. Types are chosen per Link at creation, not per team or per Collection, and nothing about a Link's type restricts what it can point at. One constraint worth knowing before you commit: a Link's slug is fixed after creation. You can repoint it, reassign it, or delete it, but you cannot convert a random Link into a custom one — you create the Link you want and retire the other. ## Related * [Random Links](/links/random-links) — how the automatic slug is generated * [Numbered Links](/links/numbered-links) — claiming a pattern and minting against it * [Custom Links](/links/custom-links) — charset rules and the reserved-word list * [What a Slug Is](/links/what-a-slug-is) — address shapes and case rules # Claim-on-Scan Source: https://help.qrtub.com/links/claim-on-scan Adopting a QR code you didn't create: how the first scan mints a Link bound to a hash of the code's contents, why a second scan never duplicates it, and what adopting does not change Claim-on-scan is what happens when you scan a QR code QRtub has never seen — a sticker a previous contractor applied, a manufacturer's serial-number label, an asset tag from a system you no longer use. Instead of shrugging, QRtub adopts the code: it creates a Link bound to that code's contents, so every later scan of the same physical code resolves to the same Link. It is how you bring existing labels into QRtub without relabeling anything. ## How a foreign code gets recognized again QRtub cannot store the third-party code's text as a slug — it isn't a QRtub address, and it may be any length or format. So it stores a fingerprint instead: a SHA-256 hash of the decoded text, with the surrounding whitespace trimmed. That hash is the lookup key. Scan the same sticker next month and QRtub hashes what it reads, finds the match, and opens the Link you already have. QRtub also keeps the original decoded text alongside the hash, so the Link's details panel can show you what the code actually says — a hash can't be reversed, so without that copy you'd have no way to recognize the code again. ## Scanning twice is safe Adoption is idempotent. Before minting anything, QRtub checks whether the scanned code already resolves — either as one of its own slugs, or by that hash — and if it does, it returns the existing Link and creates nothing. Two people scanning the same tag on the same morning end up with one Link, not two. ## What you get is an ordinary Link The Link created by an adoption is a plain Random Link underneath: a five-character slug of its own, unattached, with no destination until you set one. From that point it behaves like any other Link — assign it to an Item, point it at a URL, put it in a print batch, delete it. The only difference is the fingerprint it carries, which is what lets the in-app scanner find it again from the original sticker. ## The limit that matters: the physical code still says what it always said Adopting a code does not change the code. The sticker on the machine still encodes whatever text the previous system printed into it, and QRtub cannot alter that. So a member of the public pointing their phone camera at that sticker goes wherever the original text sends them — a dead vendor URL, a bare serial number, nothing at all. The adopted Link is reachable through **QRtub's own scanner, by someone signed in to your team**, not by an anonymous scan of the old code. That makes claim-on-scan a bridge, not a substitute for relabeling. It is genuinely useful for internal workflows — walk the yard, scan whatever tag is already on each machine, and get straight to that machine's Item — and it buys you time before a reprint. But if you need the public, or a contractor without an account, to reach your Page by scanning, that code has to carry a QRtub Link, which means a new tag. ## Related * [The In-App QR Scanner](/print-first/scanner) — the camera, paste and scan-gun entry points * [Adopting an Unknown Code From the Scanner](/print-first/adopting-a-code) — the scanner's own flow, step by step * [Random Links](/links/random-links) — the slug an adopted code's Link gets * [What a Link Is](/links/what-a-link-is) — what the new Link can carry once it exists # Custom Links Source: https://help.qrtub.com/links/custom-links Choosing your own slug: the exact character rules QRtub enforces, the reserved words it blocks, and why a slug can be refused even when nothing appears to be using it A Custom Link is one where you type the slug yourself: `qrtub.com/boardroom`, `qrtub.com/site-office`, `qrtub.com/menu_2026`. Use it when a person will read the address aloud or type it from memory — a room sign, a poster, a card — rather than scan it. Custom Links are created one at a time. Each one is checked for availability as it is created, so they are the wrong tool for a print run of hundreds; use Random or Numbered for that. ## The character rules A custom slug must: * be **3 to 50 characters** long * contain only **lowercase letters, digits, hyphens and underscores** * **start** with a letter, a digit or an underscore * **end** with a letter or a digit * contain no **two hyphens in a row** Anything you type is lowercased and trimmed first, so entering `My-Product` gives you `my-product` rather than an error. Everything else is a hard rejection: `ab` is too short, `site office` contains a space, `crane-` ends with a hyphen, `red--crane` has a double hyphen. Consecutive underscores are fine. These rules are enforced when the Link is written, not only in the form, so the same limits apply to slugs created through a CSV import. ## Reserved words QRtub blocks a list of slugs outright, because handing them out would collide with its own addresses or mislead the people scanning them. The list covers: * **App and system paths** — `app`, `api`, `r`, `login`, `signup`, `auth`, `account`, `checkout`, `static`, `assets` * **Marketing and public pages** — `pricing`, `about`, `contact`, `features`, `docs`, `help`, `support`, `faq`, `blog`, `terms`, `privacy`, `security`, `status` * **Brand terms** — `qrtub`, `qr`, `qrcode`, `link`, `thing` * **Dashboard and identity words** — `admin`, `dashboard`, `settings`, `console`, `user`, `users`, `me`, `team`, `teams`, `org` * **Plan and platform words** — `pro`, `plus`, `premium`, `enterprise`, `ios`, `android`, `download`, `mobile` The check ignores case, so `Admin` is blocked for the same reason `admin` is. The practical consequence: short, generic, single-word slugs are the ones most likely to be refused. Add something specific — `qrtub.com/acme-support` instead of `qrtub.com/support` — and you are almost always clear. ## Two other reasons a slug can be refused **It is already in use.** Slugs are unique across every team in QRtub, compared without regard to case. If someone else holds `boardroom`, you cannot have it, and QRtub says so rather than quietly giving you a variant. **It falls inside a numbered pattern your team owns.** This is the one that looks like a bug and is not. If your team has claimed the pattern `cra` + 4 digits, then `cra0042` is reserved for that pattern's use — even though no Link has been minted at that number yet, and nothing appears in your Links list using it. QRtub rejects the custom slug because minting it would let a hand-typed address hijack a slot the numbering scheme is counting on. Pick a slug outside the pattern's shape, or use a Numbered Link if that number is genuinely what you want. ## The slug is permanent Once created, a custom slug cannot be edited. You can change where it points as often as you like, turn it off, or delete it, but the address itself is fixed — a printed sign has to keep resolving. Get the spelling right before you commit, and where a mistake has already been printed, create the corrected Link and retire the old one rather than trying to rename it. ## Related * [Choosing a Link Type](/links/choosing-a-link-type) — when a random or numbered slug fits better * [Numbered Links](/links/numbered-links) — what a claimed pattern reserves, and why it can block a custom slug * [What a Slug Is](/links/what-a-slug-is) — the address shape a custom slug produces * [What Is a Destination?](/destinations/what-is-a-destination) — pointing the Link somewhere once it exists # Deleting, Unassigning, and Releasing Links Source: https://help.qrtub.com/links/deleting-and-releasing-links Three different things that look similar: permanently deleting a Link, detaching it from an Item yourself, and QRtub automatically releasing it when the Item or Collection is deleted There are three separate outcomes here, and mixing them up is how printed codes get orphaned: | Action | What happens to the Link | Who triggers it | | ------------ | ---------------------------------------------------------------- | ------------------------------------------------------------ | | **Delete** | Gone permanently. The slug stops resolving. | You, explicitly | | **Unassign** | Stays alive, detached from its Item, back in the unassigned pool | You, explicitly | | **Release** | Same as unassign — stays alive, detached | QRtub, automatically, when the Item or Collection is deleted | The short version: deleting an Item never deletes its Link, and that is on purpose. ## Deleting a Link is permanent From the Links page, open a Link's row menu and choose **Delete**. There is no archive, no trash, and no undo: the row is removed and the slug stops resolving. Anyone who scans a code carrying that slug gets "page not found". Delete a Link when it was created in error and never printed. If the code has already been produced, unassigning is almost always what you actually want, because the physical tag outlives the record. **Deletion is blocked for Links in a live print batch.** If a Link belongs to a print batch that has moved past Draft — Printing, Printed or Installed — QRtub refuses the delete. That guard exists so an accidental click cannot orphan a code that is already on a machine. In a bulk delete it applies to the whole selection: if any Link in it sits in a protected batch, the entire operation is rejected and nothing is deleted, rather than some rows disappearing silently. Two things about that block are worth knowing before you go looking for a way around it. Archiving the batch does not lift it — the check looks at the batch's status, and archiving is a separate flag. And status only steps one stage at a time, so a Printing batch can go back to Draft, a Printed batch can go back via Printing, but **Installed is terminal**: a Link in a Installed batch cannot be deleted at all. Unassign it instead, which is the action that fits a code already in service anyway. ## Unassigning keeps the Link and frees it up Unassigning detaches a Link from its Item and leaves everything else intact. The slug still resolves, the printed code still works, and the Link goes back into your unassigned pool ready to be attached to something else. Two places to do it: * **A single Link:** open the Link's details and use **Unassign** next to the Item it is attached to. Once unassigned, you can point the Link straight at a URL instead. * **Many at once:** select Links in the list and use **Unassign from Items** from the bulk menu. Unlike deletion, unassigning is not blocked by print status — that is the point. A code in a Printed batch is exactly the kind of code you want to detach and reuse rather than destroy. Once a Link is unassigned, it behaves like any other Unallocated Link: a scan shows a neutral "not connected yet" page instead of an error, and a signed-in team member scanning it can attach it to something on the spot. ## Deleting an Item or a Collection releases its Links automatically This is the behavior people are surprised by, so it is worth stating plainly: **deleting an Item does not delete the Links attached to it.** QRtub detaches them first, then deletes the Item. The Links survive, unassigned, and every physical code out in the field keeps resolving. Deleting a whole Collection does the same thing for every Item inside it. The Collection and its Items go; the Links are released into the pool. The reason is the print run. Equipment gets sold, scrapped and re-registered, but the plate riveted to it is still there. If deleting a record destroyed its Link, disposing of one machine would leave a live tag pointing at nothing — and you would find out from whoever scanned it. This is not configurable. There is no setting that makes Item deletion cascade into Link deletion; if you want the Links gone too, delete them yourself afterwards, at which point the print-batch guard above applies. ### The one exception Importing a Collection backup in **Replace** mode is different. Replace deletes the existing Items outright rather than detaching their Links first, so Links attached to those Items are deleted along with them — including Links whose codes are already printed and installed. If you are about to restore a backup over a Collection whose codes are in the field, use Merge, or export the Links you care about first. ## Related * [Bulk Assigning, Unassigning, and Deleting Links](/bulk-links/assign-unassign-delete) — doing any of this to thousands of Links at once * [Unallocated Links](/links/unallocated-links) — what a released Link does while it waits * [Importing a Collection Backup](/collections/import-backup) — Merge versus Replace, and what Replace destroys * [Archiving and Deleting Batches](/print-batches/archiving-and-deleting) — clearing the batch status that blocks a delete # Numbered Links Source: https://help.qrtub.com/links/numbered-links Reserving a prefix + digits + suffix pattern, then minting Links against it one at a time, at a specific number, or as a range of up to 1,000 A Numbered Link has a slug built from three parts you decide: a prefix, a zero-padded number, and a suffix. Claim the pattern `CRA` + 4 digits + `TL` and you get `qrtub.com/CRA0042TL`. It exists so the address on a tag can be the same identifier as the number stamped on the tag — one number for your crew to remember instead of two. Numbered patterns are included in the Professional plan (one pattern) and Scale (up to five). The Starter plan covers Random and Custom Links. ## The pattern is what you actually reserve A pattern is the combination of prefix, digit count and suffix. `CRA` + 4 digits + `TL` reserves the whole space from `CRA0000TL` to `CRA9999TL` for your team — not just the numbers you have used so far. Three things follow from that: * **A pattern is claimed exclusively across all of QRtub.** If another team already holds that exact combination, you cannot claim it, and QRtub tells you so instead of quietly giving you something else. * **Matching ignores case, storage does not.** The affixes are stored exactly as you typed them, so the address can print as `CRA0042TL`, while `cra0042tl` still resolves. You cannot own both `CRA` and `cra` versions of the same pattern — they are the same pattern. * **The reserved space is protected from Custom Links too.** A custom slug that would land inside a pattern you own — `cra0042tl`, or any other number in that range — is rejected even though no Link has been minted at that number yet. Set the digit count deliberately. It can be 1 to 10 digits, it is part of the pattern's identity (3 digits and 4 digits are two different patterns), and it sets the ceiling: a 3-digit pattern stops at 999, and QRtub refuses to mint a number that does not fit rather than producing an over-length slug. You can claim a pattern up front, or just start creating Links with it — the first Link claims the pattern automatically if it is free. ## Prefix and suffix are not validated the way custom slugs are QRtub stores whatever you type as the prefix and suffix. There is no charset check and no reserved-word check on them, unlike a custom slug. Keep them to letters, digits and hyphens: anything that needs escaping in a URL — a space, a slash, `?`, `&`, `#` — is a problem you will only discover when someone in the field tries to scan or type the address. ## The three ways to mint a number Once a pattern exists, choose a **Generation Mode** in the create form: **Auto** takes the next number in the sequence and moves the counter forward. This is the everyday mode — create ten Links and you get the next ten numbers. Auto never goes back to fill a hole left by a deleted Link. **Specific** mints one exact number, which is how you fill those holes. `0` is a valid number (it mints `CRA0000TL`). If the number already exists, QRtub rejects the request and tells you which address is in the way rather than creating a duplicate. **Range** mints a block: enter a From and To number and QRtub creates everything between them. This is the mode for a print run. ## Range mode checks for conflicts before it commits Before you confirm a range, QRtub checks the requested numbers against what already exists and shows you the answer: how many of the numbers you asked for are available, how many already exist, and which specific numbers those are (the first ten, plus a count of the rest). If the pattern is owned by another team, you find out here rather than after the fact. Confirm, and the numbers that already exist are **skipped** — you get Links for the available numbers only, and nothing existing is overwritten. So requesting 1–500 when 12 numbers are already used creates 488 Links. One range request is capped at 1,000 numbers. Larger runs are several requests: the app warns you before you submit, and the server refuses the request with "Range too large. Maximum 1000 numbers per request." ## Deleting a pattern A pattern can only be deleted once no Links exist against it. If any do, QRtub refuses with a message telling you to deal with those Links first. Read that literally: **unassigning the Links from their Items is not enough.** The check counts Links belonging to the pattern regardless of whether they are attached to anything, so the Links themselves have to be deleted before the pattern will release. If any of them are in a print batch that has moved past Draft, they cannot be deleted at all until that batch is archived — which is deliberate, since those codes are physically out in the world. ## Related * [Choosing a Link Type](/links/choosing-a-link-type) — numbered versus random versus custom * [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links) — what has to happen before a pattern will release * [Bulk Link Import via CSV](/bulk-links/csv-import) — creating numbered Links from a spreadsheet of existing asset numbers * [Building an Item ID Mask](/collections/item-id-mask) — using a pattern as a Collection's Item ID format # Random Links Source: https://help.qrtub.com/links/random-links The default Link type: a five-character slug QRtub draws for you, served under /r/, with no length or charset options to configure A Random Link is one whose slug QRtub picks: five characters of letters and digits, served at `qrtub.com/r/{slug}`. You cannot choose the slug, and there is nothing to configure — which is exactly why it is the default and the fastest way to get printable codes. ## How the slug is generated QRtub draws five characters from a base62 alphabet (`A–Z`, `a–z`, `0–9`) and stores the result in lowercase, so the address you see and print is always lowercase letters and digits, like `qrtub.com/r/x5fgd`. The length and the alphabet are fixed. There is no setting for a longer slug, a shorter one, or a different character set anywhere in QRtub — if you send a request asking for one, it is ignored and the standard five-character slug is minted instead. Before using a slug, QRtub checks that it is free. If the first draw is taken it tries again, up to a hundred times, and only fails if it somehow cannot find an unused slug in that many attempts. In practice you never see this; it is why creating five hundred random Links never asks you to resolve a conflict. ## Creating them On the Links page, open the create form and choose **Random** as the strategy. Set **Number of Links** — the form accepts up to 100 in one request — and create. Each Link comes into existence unattached: a real, resolvable address with no Item, no Page and no destination until you give it one. Random is also the type QRtub uses when a Collection is set to mint a Link automatically for each new Item. That is a Collection-level setting rather than a property of the Link itself. ## The one gotcha: case matters Random slugs are matched case-sensitively. `qrtub.com/r/x5fgd` resolves; `qrtub.com/r/X5FGD` does not — it returns "page not found", not a helpful redirect. Because slugs are stored lowercase, the practical rule is simple: print and type random addresses entirely in lowercase. This is the only Link type with that behavior. Numbered and custom slugs resolve regardless of case, which is worth remembering if the people using your codes are likely to type addresses instead of scanning them. ## Don't forget the `/r/` A random slug lives under `/r/`, and the prefix is part of the address. `qrtub.com/x5fgd` is not the same URL as `qrtub.com/r/x5fgd` and will not find the Link. When you print a readable address underneath a QR code — and you should, because codes get scratched and painted over — print the whole thing including `/r/`. ## Related * [Choosing a Link Type](/links/choosing-a-link-type) — when a numbered or custom slug is the better call * [What a Slug Is](/links/what-a-slug-is) — address shapes and case rules across all three types * [Downloading QR Codes](/bulk-links/downloading-qr-codes) — turning a batch of new Links into printable images * [Unallocated Links](/links/unallocated-links) — what a freshly created Link does before you attach anything # Unallocated Links Source: https://help.qrtub.com/links/unallocated-links Why a Link can exist with nothing attached to it yet, what that enables, and what a person sees if they scan one before you connect it An **Unallocated** Link is one that exists — it's a real, permanent slug you can print today — but doesn't have a destination, an Item, or a Page attached yet. If you weren't expecting that, it looks like something's broken. It isn't. It's the thing that makes it possible to work out of order at all. ## Why this feels wrong at first Most systems only let you create a record once you know what it's for. QRtub doesn't work that way: a Link's only real job is to exist at a stable address. Everything else — what it points to, which Item it belongs to, whether a Page is behind it — can happen whenever that part is actually ready, not when the Link was created. So seeing "Unallocated" on a batch of codes doesn't mean setup is incomplete. It means the part that needed to happen first — printing, before a lead time ran out — has happened, and the rest is still ahead of you on purpose. ## What this actually enables * **Printing before you know the destination.** Order and print a batch now, decide what each code opens once you know. * **Spares.** A few extra codes in every batch that don't belong to anything yet, ready the day something replaces a damaged tag or a new piece of equipment shows up. * **A shortener, and nothing more, for as long as you like.** A Link can point straight at a URL for its entire life and never have an Item or a Page — see [What a Link Is](/links/what-a-link-is) for why that's a complete setup rather than a partial one. None of these are workarounds. They're the same mechanism — a Link doesn't need anything else to exist — used for different reasons. ## What happens if someone scans one An Unallocated Link resolves to a plain "not connected yet" page rather than an error. If it's already installed somewhere the public can reach it, that's what they'll see until you connect it. If a batch is print-only and not yet applied to anything, this never comes up — nobody scans a code that's still in a box. Someone signed in to the team that owns the Link sees something more useful: the same page, with the option to assign the code to an Item there and then from their phone. The person applying tags can connect them on the spot without going back to a desk. ## Related * [The Print-First Workflow](/print-first/overview) — ordering and applying tags before the equipment exists * [Print Batches](/print-batches/overview) — tracking a production run, allocated or not * [Preparing Your Print Job](/suppliers/preparing-your-job) — getting a batch of these actually made * [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links) — how Links become unallocated again # What a Link Is Source: https://help.qrtub.com/links/what-a-link-is A Link is a QRtub-owned slug that resolves to a destination — and the simplest valid one is just a slug pointing at a URL, with no Item, Collection or Page attached A Link is a short address QRtub owns — a slug — plus a rule for where that address sends someone. `qrtub.com/r/x5fgd` and `qrtub.com/exc203` are both Links. A QR code is one way to encode a Link; an NFC tag, a printed line of text someone types, or a plain hyperlink work equally well, because all any of them has to carry is a URL. ## The simplest valid Link is a slug and a URL A Link needs exactly two things: the team that owns it, and its slug. Everything else is optional. There is no requirement for an Item, a Collection, or a Page — a Link that points straight at `https://example.com/manual.pdf` is a complete, fully supported Link, not a half-finished one. When a Link has its own destination and no Item attached, a scan redirects immediately to that destination. That is the whole behavior. You can use QRtub this way forever: print a hundred codes, point each one at a URL, change those URLs whenever you like, and never create a single Item. ## Why it behaves like an ordinary URL shortener Because in the base case it is one. Someone opens the slug, QRtub looks it up, QRtub redirects. That is the same three steps any link shortener runs, and nothing QRtub-specific is needed to make it work. What QRtub adds is everything around that redirect: the destination is stored on the server rather than baked into the printed code, so you can change where a code goes without reprinting it; slugs can be minted in bulk before you know what they are for; and a Link can be attached to an Item and open a Page with several Destinations instead of redirecting to one. None of that changes the mechanism underneath, which is why a Link feels familiar the first time you use one. ## What a Link can carry * **A destination URL.** One address, optionally built from a template that inserts an Item's own field values, like `app.com/inspect?id={{item.assetID}}`. Values are inserted exactly as stored — QRtub does not URL-encode them, so a field containing a space, `&`, `?` or `#` produces a broken address. * **An assignment to one Item.** A Link points at no more than one Item, though one Item can have several Links pointing at it. * **A Page.** With an Item attached, the Link can open a Page listing multiple Destinations instead of redirecting to a single one. * **An active/inactive switch.** Switching a Link off does not show a friendly notice — an inactive Link returns a plain "page not found" to anyone who scans it. If you want a code to stay polite while you decide what it does, leave it active and unattached instead. ## Where Links live Links belong to a team, not to a Collection. That is why a Link can be assigned to an Item in any of the team's Collections, and why deleting a Collection does not take its team's Links with it. A Link's slug is fixed once it is created. You can change where a Link goes as often as you want, but you cannot rename it — the printed code has to keep resolving. ## Related * [What a Slug Is](/links/what-a-slug-is) — the identifier part of the address, and the case rules that come with it * [Choosing a Link Type](/links/choosing-a-link-type) — Random, Numbered or Custom, and when each is the right call * [Unallocated Links](/links/unallocated-links) — a real, printable Link with nothing attached yet * [What Is a Destination?](/destinations/what-is-a-destination) — where a scan actually ends up # What a Slug Is Source: https://help.qrtub.com/links/what-a-slug-is The identifier segment of a Link's address — the two URL shapes it produces, and why random slugs are case-sensitive while numbered and custom ones are not The slug is the part of a Link's address that identifies it: the `x5fgd` in `qrtub.com/r/x5fgd`, the `exc203` in `qrtub.com/exc203`. Everything else in the URL is fixed. When QRtub asks how you want a Link created, it is really asking how you want its slug chosen. ## The slug is not the whole address There are two address shapes, and which one you get depends on the Link's type: | Link type | Address shape | Example | | --------- | -------------------- | --------------------- | | Random | `qrtub.com/r/{slug}` | `qrtub.com/r/x5fgd` | | Numbered | `qrtub.com/{slug}` | `qrtub.com/exc203` | | Custom | `qrtub.com/{slug}` | `qrtub.com/boardroom` | Random Links sit under `/r/` and the other two sit at the root. That separation is deliberate: `qrtub.com/r/abc12` and `qrtub.com/abc12` are two different addresses resolved by two different routes, so the automatic slugs never collide at scan time with the ones you choose yourself. The domain is always lowercase `qrtub.com`. When you print a Link as readable text under a QR code, print the whole address — including `/r/` if it is a random Link — because the slug alone will not get anyone anywhere. ## Case matters for random slugs, and not for the others This is the one slug rule that catches people out: * **Random slugs are matched case-sensitively.** They are stored in lowercase, so the address you see and print is lowercase, and it has to be typed that way. `qrtub.com/r/X5FGD` will not resolve to `qrtub.com/r/x5fgd`. * **Numbered and custom slugs are matched case-insensitively.** A numbered Link keeps whatever case you typed when you claimed the pattern, so it can print as `qrtub.com/CRA0042TL`, and someone typing `cra0042tl` still lands in the right place. Custom slugs are stored lowercase and resolve either way. If your crews type addresses by hand — and on a muddy site with a cracked screen, some will — a numbered or custom slug is more forgiving than a random one. ## Slugs are unique across all of QRtub, not just your team Slugs are checked against every Link in QRtub, not just your team's. If another team already holds `boardroom`, you cannot have it, and QRtub tells you it is in use rather than quietly giving you something else. The check ignores case, so `Boardroom` is not available either. Random slugs go through the same check when they are minted, which is why you never have to think about it — QRtub keeps drawing new ones until it finds a free slug. A slug is fixed once the Link exists. There is no rename: the point of the whole system is that a printed code keeps resolving, and renaming a slug would break every code already in the field. If you need a different address, create a new Link and, if the old one is no longer wanted, delete it. ## What varies by type Each type has its own rules about what characters a slug may contain and how long it can be — a random slug is always five characters, a custom slug is validated against a fixed charset and a reserved-word list, and a numbered slug is built from a prefix, a zero-padded number and a suffix. Those rules live with each type rather than here. ## Related * [Choosing a Link Type](/links/choosing-a-link-type) — which slug strategy fits which job * [Random Links](/links/random-links) — the automatic five-character slug * [Numbered Links](/links/numbered-links) — prefix, digits, suffix and claimed ranges * [Custom Links](/links/custom-links) — charset rules and reserved words # ActionLink: The Destination Button Source: https://help.qrtub.com/pages/action-link The one section that is a Destination button — its fields, why it hides itself when a binding cannot resolve, and how adjacent ActionLinks merge into one block ActionLink is the section that sends someone somewhere. Every other section displays information; this one is a Destination. If a Page offers three systems, it has three ActionLinks. It renders as a card: an optional 40-pixel icon on the left, a bold label, an optional description underneath, and a chevron on the right. Tapping anywhere on the card follows the link. ## Its settings | Setting | Notes | | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | **Label** | The button text. Bindable. If no label is set, the URL is shown instead | | **Link URL** | The Destination. Bindable, and usually is — this is where `{{item.serial_number}}` and friends go | | **Description (Optional)** | A line of supporting text. Long text is truncated with a more/less control | | **Icon Image** | Bindable. Defaults to the Item's image | | **Open in new tab** | Off by default, so the Destination replaces the page | | **Fallback URL** / **Fallback Message** | Only used when the Link URL is an app deep link and the app does not open. See [App Links & Fallback URLs](/destinations/app-links) | A new ActionLink arrives pre-bound to the Item — label from `{{item.name}}`, description from `{{item.description}}`, icon from `{{item.image}}` — and with a placeholder Link URL that points at a field most Collections do not have. So a freshly added ActionLink is normally invisible until you give it a real URL, which is the behavior described next, not a bug. ## It hides itself rather than showing a broken button **If any binding in the Link URL cannot be resolved, the whole ActionLink is removed from the page.** Same if the URL resolves to nothing but whitespace. A machine with no serial number simply does not show the "Open in the CMMS" button, instead of showing a button that leads to a 404. This is specific to ActionLink. Button and Link sections do not do it — they will happily render a dead control. In the editor, a hidden ActionLink is not invisible: it stays on the canvas with a dimmed orange outline so you can see it and fix the missing field. Switch on **Preview** and it disappears, the same as it would for a real visitor. Two consequences worth planning for: * A partially filled Collection will show different numbers of buttons on different Items. That is usually what you want, and it is the reason to bind the URL rather than hardcode it. * The Item field the URL depends on is the thing to check first when a button "vanishes." Step through Items with the preview selector to see which ones come up short — see [Previewing a Page](/pages/previewing-a-page). ## Values are inserted exactly as stored There is no automatic URL encoding. A field value containing a space, an `&` or a `?` is dropped into the URL as-is and will break the link — the button appears, it just goes somewhere wrong. If you are building a query string from free-text fields, keep the values URL-safe at the source. The full rules are in [Field Bindings & URL Templates](/destinations/field-bindings). Link URLs are also checked for script-executing schemes before rendering. A `javascript:` or `data:` URL is neutralized rather than made clickable, whether you typed it or a field supplied it. ## Adjacent ActionLinks merge into one block When two or more ActionLinks sit next to each other, they lose the gap between them and the rounded corners in the middle, so the group reads as one segmented block of buttons rather than a stack of separate cards. The grouping is worked out from what will actually be visible. A hidden ActionLink — hidden by a condition, or by an unresolvable URL — is skipped, so the two links either side of it still join correctly and you never get a stray flat edge where something was removed. Putting any other section between two ActionLinks (a Spacer, a Text block) breaks the group deliberately. ## Related * [Section Types](/pages/section-types) * [App Links & Fallback URLs](/destinations/app-links) * [Field Bindings & URL Templates](/destinations/field-bindings) * [Conditional Visibility](/destinations/conditional-visibility) # AdminToolbar Source: https://help.qrtub.com/pages/admin-toolbar The button bar pinned to the bottom of a Page, visible only to signed-in team members by default, for shortcuts the public should not see AdminToolbar is a bar of your own buttons fixed to the bottom of the page — icon above a short label, spread evenly across the bar in the page's accent color. Its point is that it defaults to showing only when the viewer is signed in, so you can put internal shortcuts on a page the public also scans. A yard supervisor scanning a forklift sees a row of internal shortcuts along the bottom. A customer scanning the same forklift sees the page without them. ## What it comes with Add an AdminToolbar and it arrives with three buttons already configured: | Button | Goes to | | -------------- | -------------------------------------------------------------------------------------------------------- | | **QR Codes** | Your Links list | | **Edit** | This Item, open in the app for editing | | **Manage Tub** | This Collection's settings — the default label still carries the old name for a Collection, so rename it | Those default URLs use bindings — `{{collection.id}}` for the Collection and `{{item.id}}` for the Item — so they point at whatever you are looking at rather than at a fixed record. ## Configuring buttons Each button has three parts: a **label**, a **URL**, and an **icon** chosen from a curated set of around 110 common icons (tools, arrows, documents, devices, brands). An icon name the app does not recognize falls back to a plain circle rather than failing. The URL can be anything a link can be — an app page, an external system, an app deep link. Bindings work in it, with the same no-URL-encoding rule as everywhere else: a field value containing a space or an `&` will break the link. Two silent behaviors to know: * **A button with an empty label or an empty URL is dropped.** It does not render as a half-button; it is simply not there. * **If no button survives that check, the whole toolbar renders nothing.** An AdminToolbar with three blank rows is invisible, and looks identical to one that is hidden by its condition. Keep the count modest. The bar centers itself in a column about 480 pixels wide and divides the space evenly, so a handful of buttons reads well on a phone and a long list turns into unreadable slivers. ## The signed-in default, and how to change it The visibility is not hardcoded — it is an ordinary section condition, pre-filled with a check for a signed-in viewer. You will find it in the **Visibility** group of the Properties panel. That means you can change it like any other condition: clear it to show the toolbar to everyone, or replace it with something narrower. The usual caution applies — an undefined identifier makes the whole condition evaluate to false silently, so a typo hides the toolbar with no error shown. See [Conditional Visibility](/destinations/conditional-visibility). **Being signed in is not the same as being on your team.** The default condition asks whether anyone is signed in to QRtub, not whether they belong to the team that owns the Collection. Do not put anything genuinely sensitive behind it. If a page must not be seen by outsiders at all, make the Item private instead — that is a real membership check. See [Page Privacy: Public vs. Private](/pages/page-privacy). ## It always renders last Wherever the AdminToolbar sits in the Structure tree, it is rendered at the very end of the page and fixed to the bottom of the viewport, floating above the content as the visitor scrolls. Its row in the Structure panel has no drag handle and no move controls, because moving it would change nothing. The page adds extra bottom padding when a toolbar is present so the footer is not trapped underneath it. ## It always appears in the editor Previews are always treated as signed in, so the default condition is always true there. The AdminToolbar shows in the Page Editor canvas, in Preview mode, and in the read-only previews in Collection and Item settings — including for pages where no real visitor will ever see it. The only way to check what an anonymous scan looks like is to open the Link in a browser you are not signed in to. ## Related * [Section Types](/pages/section-types) * [Conditional Visibility](/destinations/conditional-visibility) * [Page Privacy: Public vs. Private](/pages/page-privacy) * [Previewing a Page](/pages/previewing-a-page) # Direct Mode vs. Page Mode Source: https://help.qrtub.com/pages/direct-mode-vs-page-mode The Collection default and per-Item override that decide whether a scan redirects immediately or opens a Page — and the inheritance rule between them Two things can happen when someone scans a QR code, and one setting decides which: * **Direct Mode** — the scan goes straight to a single Destination. No page, no tap. The visitor lands in the vendor's system. * **Page Mode** — the scan opens the Item's Page, where the visitor picks from the Destinations you put there. You can switch between them at any time without reprinting. The printed code encodes the Link, never the Destination, so changing mode changes behavior on codes already stuck to equipment. ## Where each is set **The Collection sets the default.** In the Collection's settings, the **Scan behavior** tab has one toggle, **Show a profile page**: on means new Items start in Page Mode, off means they start in Direct Mode. Turning it on also reveals the Collection's page tab and the Page Editor; turning it off surfaces a **Default destination** builder instead, because a pass-through Item needs somewhere to send the scan. **The Item can override it.** Open an Item, go to its **Destination** tab, and pick one of two radio buttons: * **Destination Link** — redirect to a URL when scanned. This is Direct Mode. * **Landing Page** — show the Item's page. This is Page Mode. (The radio is labeled "Landing Page" in the current app. The canonical name for the thing it produces is a Page.) ## The inheritance rule An Item's own explicit choice always wins. An Item that has never made one inherits the Collection's default. That second half is the part that surprises people. Items created by CSV import, or created before you last flipped the Collection toggle, may carry no explicit choice at all — so flipping the Collection default changes how those existing Items resolve, not just new ones. Items that have been saved through the Item form do carry an explicit choice, and they will not move. ## Conditional Destination rules force a redirect One exception is worth knowing because it looks like a bug. If an Item carries active conditional Destination rules, it **always** redirects — even when its mode resolves to Page Mode. The rules are evaluated and the scan is routed; the Page is not rendered. So if you added routing rules to an Item and its page stopped appearing, that is why. Clear the rules to get the Page back, or move the branching into the Page itself by putting conditions on individual sections. See [What Is a Destination?](/destinations/what-is-a-destination). ## Choosing between them Direct Mode is right when a scan has exactly one sensible outcome — a product page, one asset record, one form. It is the fastest possible path for the person scanning, and it is what most single-purpose codes want. Page Mode is right when one code has to serve more than one purpose or more than one audience: the inspection app for the operator, the manual for the technician, a support form for the customer. One code, several Destinations, no second sticker. A Direct-Mode Item with no resolvable Destination does not fall back to a Page. It shows a "this link isn't ready yet" screen instead, which tells a signed-in owner how to fix it and tells everyone else nothing useful — so leaving the Destination blank is not a way to get a Page. ## Related * [Pages Overview](/pages/pages-overview) * [Scan Behavior for New Items](/collections/scan-behavior-default) * [What Is a Destination?](/destinations/what-is-a-destination) * [Default Destination for New Items](/collections/default-destination) # Image Display Controls Source: https://help.qrtub.com/pages/image-display-controls Frame Shape, Image Fit and Image Alignment — the shared controls that decide how an image is cropped and positioned in ImageSection, ItemHeader and Hero Three settings decide how an image sits in its space, and they work identically in the three sections that display images: **ImageSection**, **ItemHeader** and **Hero**. You will find them in the Media group of the Properties panel. They exist because Item photos are never a consistent shape. A page has to look right whether someone uploaded a tall phone snap of a serial plate or a wide shot of a machine. ## Frame Shape Frame Shape sets the space the image is given, before anything is done to the image itself. | Option | Shape | | -------------------- | --------------------------------------------------------------------------------- | | **Square (1:1)** | Equal width and height | | **Portrait (3:4)** | Taller than wide | | **Landscape (16:9)** | Widescreen | | **Natural Size** | No fixed frame — the image keeps its own proportions and the section grows to fit | The first three give every Item the same shape regardless of what was uploaded, which is what keeps a Collection of two hundred pages looking like one design. Natural Size gives up that consistency in exchange for never cropping anything. ## Image Fit Fit only applies inside a fixed frame, and answers what to do when the image and the frame are different shapes. * **Fit (Shrink to Fit)** — the whole image is visible, letterboxed with empty space on two sides. Nothing is lost. * **Fill (Crop to Fill)** — the image covers the whole frame and the overflowing edges are cut off. No empty space, but you lose part of the picture. Choose Fit when the image contains information — a nameplate, a wiring diagram, a serial number. Choose Fill when the image is decorative and you care more about a tidy block of color. **With Frame Shape set to Natural Size, Image Fit does nothing.** There is no frame to fit inside, so the setting is inert rather than wrong. ## Image Alignment Alignment decides which part survives, or where the image sits. * In a **fixed frame with Fill**, it chooses which edge is kept when cropping: left, center or right. A machine photographed off to one side of the shot may need this. * In a **fixed frame with Fit**, it positions the shrunk image within the letterboxed space. * With **Natural Size**, it positions the whole image in the section: flush left, centered, or flush right. There is no vertical alignment control — the choice is horizontal only. ## The defaults are different per section Each section starts from what usually looks right for it, so do not expect the same three values everywhere: | Section | Frame | Fit | Alignment | | ---------------- | ---------------- | -------- | --------- | | **ImageSection** | Landscape (16:9) | Fit | Center | | **ItemHeader** | Square (1:1) | Fit | Center | | **Hero** | Square (1:1) | **Fill** | Center | Hero crops by default; the other two do not. If a Hero image looks cut off and an ImageSection with the same picture does not, that difference is why. ## Zoom, and the missing-image case ImageSection and ItemHeader carry an **Image Zoom** toggle, on by default, letting a visitor enlarge the image in place — useful for a photographed label that is unreadable at page size. Turn it off for decorative images where an accidental zoom is just annoying. The two sections disagree about what to do with a missing image, which is worth knowing before you build a page for a Collection where only some Items have photos: * **ImageSection** shows a "No Image" placeholder in the frame, so the layout stays the same height on every Item. * **ItemHeader** and **Hero** simply omit the image and let the text move up. Hero has no zoom toggle — its image is never zoomable. ## Related * [Section Types](/pages/section-types) * [The Page Editor Layout](/pages/page-editor-layout) * [Theming a Page](/pages/page-theming) * [What Is an Item?](/items/overview) # The Page Editor Layout Source: https://help.qrtub.com/pages/page-editor-layout Opening the editor, the three-tab left panel, the Properties panel, drag-a-field binding, and the undo history that clears when you switch Item The Page Editor is where you decide what someone sees when they scan. The page sits in the middle; a panel on each side does the work. ## Opening the editor From the Collection's settings, open the page tab and choose **Edit profile page**. The editor opens in a new browser tab. (That tab only appears when pages are switched on for the Collection — see [Pages Overview](/pages/pages-overview).) You can also open it against one specific Item: from the Item's **Page** tab, press **Edit Page**. That matters, because opening from an Item puts you in override mode — see [Per-Item Page Overrides](/pages/page-overrides). ## The left panel: three tabs Only one tab is visible at a time. | Tab | What it does | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Components** | The palette of sections you can add — searchable, grouped into Data Display, Layout, Content, Media and Interactive | | **Data** | The fields you can bind, grouped by namespace: Item Properties, Tub Properties, Device & Platform, Time & Date, Request Info, Access URL, User & Session, Theme Properties | | **Structure** | The page as a tree — reorder, nest, expand containers, and see which sections carry a condition | The Structure tab is the fastest way to work on a long page: each row shows the section type, a child count for containers, and an eye icon marking a section as currently visible or hidden by its condition. Move sections with the up and down controls, or with Alt+↑ and Alt+↓. ## The Properties panel The panel on the right shows settings for whatever is selected, or **Page Settings** for the whole page when nothing is selected. A section's settings are grouped into collapsible sections — Visibility, Content, Media, Style, Layout, Behavior, Access, General and Custom Styles — so most sections open showing only the handful of fields you usually touch. Page Settings is where theming and page width live; see [Theming a Page](/pages/page-theming). ## Adding and arranging sections 1. On the **Components** tab, find a section and add it. 2. Select it on the page to open its settings in **Properties**. 3. Switch to **Structure** to reorder, or use the up and down controls. Container and Card can hold other sections, so you can group things and style the group as a unit. AdminToolbar is the exception to arranging: it is pinned to the end of the page and cannot be dragged. Selected sections are outlined in blue. An orange outline means that section is overridden for the Item you are viewing, and a dimmed orange outline means it is currently hidden — either by its condition or, for an ActionLink, by an unresolvable link. ## Putting Item data into a section Most section settings accept a binding instead of fixed text. Bindings use double curly braces and a namespace: ```text theme={null} {{item.name}} {{item.serial_number}} {{collection.name}} ``` Rather than typing them, open the **Data** tab and drag a field straight onto the setting you want it in. One namespace in that list is a trap: the **Link** group (`link.*`) is available to Destination URLs and routing rules, but it is not part of what a Page is rendered with. Dragging one of those fields into a section leaves you with an empty value and no error. Two behaviors to expect: a binding that cannot be resolved renders as empty rather than showing an error, and most sections hide themselves when their content is empty. Values are also inserted exactly as stored, with no URL encoding — so a field containing a space or an `&` will break a URL you build from it. The full syntax reference is [Field Bindings & URL Templates](/destinations/field-bindings). ## Undo, redo, and the history gotcha Undo and redo are in the top bar, and hold the last 50 changes. **Switching to a different Item clears the undo history.** So does switching back to the base template. Finish an edit before you go looking at another Item — once you have switched, the previous work can only be undone by editing it back by hand. ## Related * [Section Types](/pages/section-types) * [Previewing a Page](/pages/previewing-a-page) * [Per-Item Page Overrides](/pages/page-overrides) * [Theming a Page](/pages/page-theming) # Page Metadata & Social Previews Source: https://help.qrtub.com/pages/page-metadata How a Page's browser title, link-preview card and search-engine directives are generated from the Item — and why pages are noindex but follow You do not write metadata for a Page. It is generated from the Item the Page is showing, every time the page is served: | Metadata | Comes from | | ------------- | -------------------------------------------------------------------------------------- | | Page title | The Item's name, or "Unnamed Item" if it has none | | Description | The Item's description — falling back to the Item's name when the description is blank | | Preview image | The Item's image | That covers the browser tab, the search-engine snippet, and the card that appears when someone pastes the Link into a messaging app or a work chat. Both OpenGraph and Twitter tags are emitted, so the major platforms all read the same values. The card is the large-image style when the Item has an image and the compact style when it does not. There is no per-Page override for any of it. If a link preview says the wrong thing, the fix is the Item's name, description or image — which also means a good Item description does double duty as the preview text. ## Pages are noindex, follow Every Page is served with instructions telling search engines **not to index it**, but **to follow** the links on it. The reasoning is worth knowing, because the first half surprises people who expected their pages to rank. A Collection of a thousand Items produces a thousand thin, near-identical pages — "Pump 4A", "Table 12" — sitting on `qrtub.com`. Indexing those would dilute the domain rather than help anyone find anything, and none of them are pages a search visitor was looking for. Following the links keeps any link equity flowing outward to the sites the page points at. None of this affects scanning. Indexing directives are advice to crawlers; the page resolves normally for any person who scans the code, whether or not it is indexed. If you need a QR code to open something that *does* rank, point its Destination at a page on your own website rather than trying to make a QRtub Page indexable — see [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode). ## Private Items get minimal metadata A private Item reveals nothing to a crawler or a link preview. Its metadata is deliberately generic — the title reads "Private Item" and the description "Sign in to view this item" — and it is marked both noindex *and* nofollow. The Item's real name, description and image never appear. So pasting a private Link into a group chat produces a bland card that gives away nothing about the equipment. See [Page Privacy: Public vs. Private](/pages/page-privacy). ## Two other cases you may see * **A printed Link that is not connected to anything yet** gets its own placeholder metadata, titled "Unassigned Link", and is kept out of the index for the same reason as everything else. A batch of pre-printed codes will not turn into a batch of indexed empty pages. * **A Link that redirects rather than opening a Page** has almost no metadata to speak of; there is no page to describe, only a redirect. ## Related * [Page Privacy: Public vs. Private](/pages/page-privacy) * [Pages Overview](/pages/pages-overview) * [Name and Description](/items/name-and-description) * [Unallocated Links](/links/unallocated-links) # Per-Item Page Overrides Source: https://help.qrtub.com/pages/page-overrides Why an edit can change every Item, what the base template is, and how the Override toggle decides whether Save touches one Item or the whole Collection If you edited a page and the change landed on every Item in the Collection, you saved to the **base template**. That is the normal, intended behavior of the Page Editor — and this page is about the one switch that changes it. The **base template** is the Collection's single page design. Every Item renders it, filled in with its own field values. It is what you are editing whenever no Item is selected, and it is what "changed everything" means: one design, four hundred Items, one save. An **override** is a per-Item exception on top of that base template — one machine that needs an extra button, one room that needs a different photo. ## The Override toggle When you are viewing a real Item in the editor, the top bar shows an **Override** toggle: * **Override: ON** (orange, unlocked) — saving stores your changes for **that Item only**. The rest of the Collection is untouched. The top bar also shows an "Item Override Mode" badge. * **Override: OFF** (locked) — saving updates the **base template**, changing the page for *every* Item in the Collection. With no Item selected there is no toggle at all, because there is nothing to override: you are editing the base template by definition. **Selecting a real Item turns Override on automatically.** That is the safe default — an experiment on one machine cannot silently reshape the other four hundred. To change the page for everyone, either switch the selector back to **Base Template**, or turn Override off deliberately. ## Saving to the base template while an Item has overrides This case gets its own warning dialog, because it does more than you might expect. If you save with Override OFF while the Item you are looking at has overridden sections, those overridden sections are **pushed into the base template** and the Item's override record is deleted. The confirm button is labeled "Apply to All Items", which is exactly what happens. The dialog lists which sections are about to be applied, so read the list before confirming. It also offers "Don't show this warning again for this tub" — that preference is remembered per Collection in your own browser, so dismissing it does not affect your colleagues, and does not carry to your other devices. ## Undoing an override Two levels, both from the editor while viewing that Item: * **One section** — select an overridden section (they carry an orange outline) and press the revert button in the Properties panel header. That section goes back to the base template version; everything else the Item overrides stays. * **Everything** — press **Revert All** in the top bar. It appears only when the Item actually has overrides, and it deletes the whole override record, putting the Item back on the base template. There is also an automatic case: if you edit an Item's page back to match the base template exactly, the now-empty override record is deleted for you rather than left behind as an empty exception. ## What an override actually stores An override is stored as a difference, not a copy of the whole page. It records only which sections were added or changed, which base sections were removed, and the section order if you reordered things. Theme and layout are recorded only if you changed them. That has a consequence worth planning around: * **Sections the Item has not overridden keep following the base template.** Fix a typo in the base template's Text block and the fix reaches every Item, including Items with overrides elsewhere. * **Sections the Item has overridden stop following it.** That section is now frozen at what you saved; later base-template edits to it will not reach this Item. * **Theme and layout are stored whole.** If an Item overrides the theme at all, it stops following the Collection's theme entirely — not just the one value you changed. ## Use overrides sparingly One machine that needs an extra button is a good reason. Restyling forty Items individually is a sign the base template should change instead — and each of those forty becomes a place a future fix silently fails to land. There is no list of which Items in a Collection carry overrides, and no bulk clear. You find them by stepping through Items in the editor and looking for orange outlines, so keeping the count small is a practical matter, not just tidiness. Overrides are also invisible in a Collection's page template history: they are not versioned. See [Page Template Versions](/pages/page-template-versions). ## Related * [Previewing a Page](/pages/previewing-a-page) * [Page Template Versions](/pages/page-template-versions) * [The Page Editor Layout](/pages/page-editor-layout) * [Duplicating an Item](/items/duplicating) # Page Privacy: Public vs. Private Source: https://help.qrtub.com/pages/page-privacy The per-Item setting that makes a scan require a signed-in team member, what a stranger sees instead, and why it is checked before any redirect By default a Page is public: anyone who scans the code sees it, no sign-in, no account. Marking an Item private changes that — the page is only viewable by a signed-in member of the team that owns the Collection. Privacy is set per Item. Open the Item, go to its **Destination** tab, choose **Landing Page**, and tick the checkbox that appears beneath it: **Private Landing page**. (That is the literal label in the current app; the canonical name for what it protects is a Page.) New Items start public. ## What a visitor actually sees When a private Item is scanned: 1. **Nobody signed in** — the visitor is sent to the QRtub sign-in screen, with a return path back to the scanned code. After signing in successfully, they land on the page. 2. **Signed in, but not a member of the owning team** — they get a plain not-found page. They are not told the Item exists, who owns it, or that they lack permission. There is no request-access flow. 3. **Signed-in team member** — the page renders normally. So a private code is not a soft nudge; to an outsider it is indistinguishable from a code that points nowhere. That is intentional, but it means a private Item is a poor choice for anything a customer or subcontractor is meant to reach. ## It gates the redirect too, not just the page The privacy check runs *before* the Destination is resolved. A private Item that is set to Direct Mode therefore still demands a sign-in first, and only redirects afterwards. Privacy is a gate on the scan, not a property of the page layout. ## What it does not protect **Private means "who may view this QRtub page", not "who may use the system it links to."** Once a viewer is on the page, every Destination button behaves normally. If a button opens a public URL, that URL stays public — the vendor system on the other end does its own authentication, or doesn't. Making the Item private does not add a password to anything you link out to. It also does not hide Item data from the page's own bindings. A private page renders the same fields a public one would; the difference is only who is allowed to load it. If your goal is to keep one button away from the public rather than the whole page, use a condition on that section instead — a section can be shown only to signed-in team members. See [AdminToolbar](/pages/admin-toolbar), which does exactly that by default, and [Conditional Visibility](/destinations/conditional-visibility). ## Effect on search engines and link previews Private pages are given deliberately minimal metadata: the title reads "Private Item", the description "Sign in to view this item", and search engines are told not to index the page and not to follow its links. Nothing about the real Item leaks into a search result or a chat-app link preview. Public pages get the Item's own name, description and image instead — see [Page Metadata & Social Previews](/pages/page-metadata). ## A note on Collection-wide privacy There is a Collection-wide private flag in the underlying data, which would gate every Item's page at once, but nothing in the app sets it today. In practice, privacy is a per-Item decision — there is no single switch that makes an entire Collection sign-in-only, and no bulk privacy action. Setting it on many Items means setting it on each of them. ## Related * [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode) * [Page Metadata & Social Previews](/pages/page-metadata) * [AdminToolbar](/pages/admin-toolbar) # Page Template Versions Source: https://help.qrtub.com/pages/page-template-versions Every save of a Collection's page design creates a numbered version, one active at a time — what that means in practice, and what the app cannot do with the older ones Every time you save the base template in the Page Editor, QRtub writes a new version of that Collection's page design rather than overwriting the old one. Versions are numbered from 1, counting up per Collection, and exactly one is active at a time — the newest. That active version is what every scan renders. You can see the number in the Page Editor: with nothing selected, **Page Settings → Page Info** shows a read-only **Version** field. If it reads v14, this Collection's page has been saved fourteen times. Each version is stamped with who saved it and when. Saves are manual — there is no autosave, so a version appears when you press Save and not before. ## Versions vs. starter templates These two are easy to confuse, and the difference is *when they act*: * A **starter template** acts **once, at the moment a Collection is created**. It seeds the Collection's fields, its first page design and some sample Items, and then it is finished — it never applies again, and there is no way to re-run it. See [Starter Templates](/collections/starter-templates). * A **page template version** is created **every time you save this Collection's page**, from then on. It is the ongoing history of the design that the starter template began. So a Collection created from the IT Assets starter template has one starter template forever and a growing pile of versions — v1 being roughly what the starter gave it, and v9 being what it looks like after nine rounds of editing. ## What versioning does and does not give you What it gives you: saves are additive, so a save never destroys the previous state at the database level, and the design's history is retained per Collection rather than being a single mutable record. What it does not give you today: * **There is no version history screen.** The editor shows the current number, not a list, and there is no way to browse or preview an earlier version. * **There is no restore button.** An older version cannot be rolled back to from the app. * **There is no "copy this page to another Collection" action.** That is worth stating plainly rather than implying: if you make a mess of a page design, undo is your recovery path within the editing session — and the undo history holds the last 50 changes and is cleared if you switch Item. Once you have saved and closed the tab, rebuilding by hand is the practical route. ## Copying a page design to another Collection The route that does exist is a Collection backup. Exporting a Collection writes a JSON file containing its settings, its field schema and its **active** page template; creating a new Collection from that file brings the page design with it. That is also the closest thing to a snapshot you can keep on purpose: export a backup when a page design is in a state you would hate to lose. See [Exporting a Collection Backup](/collections/export-backup) and [Creating a New Collection From a Backup](/collections/new-collection-from-backup). Importing a backup into an *existing* Collection replaces its page design — which, consistent with everything above, arrives as a new version rather than as an edit to the current one. ## What is not versioned * **Per-Item overrides.** An Item's exceptions are stored separately and carry no version history at all; the only recovery from a bad override is to revert it. See [Per-Item Page Overrides](/pages/page-overrides). * **Item data.** Versions cover the design, never the field values it renders. Deleting a Collection permanently deletes its page templates along with it, every version. Its Links survive and return to your unassigned pool, so printed codes keep working — but the design does not come back. ## Related * [Per-Item Page Overrides](/pages/page-overrides) * [Starter Templates](/collections/starter-templates) * [Exporting a Collection Backup](/collections/export-backup) * [Creating a New Collection From a Backup](/collections/new-collection-from-backup) # Theming a Page Source: https://help.qrtub.com/pages/page-theming Theme presets, accent color, radius, shadows, spacing, typography, light or dark, custom hex colors and page width — plus the two settings that quietly reset the others Theming lives in **Page Settings**, which is what the Properties panel shows when nothing on the page is selected. Click any empty area of the canvas to get there. The theme belongs to the page template, so it is a Collection-wide decision: change the accent and every Item in the Collection changes with it. ## Start with a preset **Theme Preset** offers seven complete looks: | Preset | Character | | --------------------- | ----------------------------------------------------- | | **Classic Light** | Clean and professional with subtle accents | | **Professional Dark** | Sophisticated dark theme for modern brands | | **Warm Minimal** | Warm tones with generous spacing | | **High Contrast** | Maximum readability with bold accents, square corners | | **Soft Pastel** | Gentle colors with very rounded corners | | **Vibrant Modern** | Bold colors with compact spacing | | **Monochrome** | Timeless grayscale with subtle depth | **Choosing a preset replaces the entire theme rather than merging with your current settings** — accent, radius, shadows, spacing, typography, light/dark, and any custom colors you had entered. So pick the preset first and adjust afterwards. Once you change anything by hand the dropdown reads "Custom / No Preset", which is normal and not an error state. ## The individual controls | Setting | Options | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Accent Color** | Seven named accents: Sky, Blue, Green, Amber, Red, Violet, Zinc. This is a fixed palette, not a color picker — each accent is a coordinated set of shades used for buttons, links and the toolbar | | **Border Radius** | None, SM, MD, LG, XL, 2XL — applied to cards, buttons and image corners together | | **Appearance** | Light Mode or Dark Mode | | **Shadows** | Light, Normal, Heavy | | **Spacing** | Compact, Normal, Spacious — the rhythm between sections | | **Typography Scale** | Small, Medium, Large — base font size and line height | **Custom Colors (Optional)** goes underneath, with seven slots you can override individually: Background, Surface, Surface Accent, Border, Text Primary, Text Secondary, and Text on Accent. They take six-digit hex values only (`#1A2B3C`); a shorthand like `#ABC` will not be accepted. Each slot has a clear control to hand the color back to the theme. **Switching Appearance clears your custom colors.** Toggling between Light and Dark discards everything in the Custom Colors block so the light or dark defaults can take over. Decide light or dark before you hand-pick colors, not after. ## Page width and padding The **Layout** group sets the container the whole page renders in: * **Max Width** — SM through 2XL, or Full Width. Pages are almost always read on a phone, so this mostly governs what happens on a desktop browser: a narrow max width keeps the page looking like a phone screen, Full Width lets it stretch. * **Padding** — the space between the page content and the edge of the screen, from None up to 12. ## Reading theme values in a binding Two theme values are readable as bindings inside the page: `{{theme.accent}}` and `{{theme.radius}}`. They return the *token name* rather than a color or a pixel value — `sky`, `xl` — so they are useful in a Custom Styles expression that needs to follow the theme, and not useful as a color you can display. The rest of the theme is not exposed as bindings. ## What the theme does not cover * **There is no logo or brand image setting in the theme.** Put a logo on the page as an ImageSection or in a TubInfo section instead. * **There is no per-Item theme by design**, but an Item override can carry one. When it does, the Item stores the entire theme rather than the one value you changed — so later changes to the Collection's theme will not reach that Item at all. See [Per-Item Page Overrides](/pages/page-overrides). * **Custom Styles on individual sections** are a separate mechanism from theming, set per section in the Properties panel, and they override whatever the theme decides. ## Related * [The Page Editor Layout](/pages/page-editor-layout) * [Previewing a Page](/pages/previewing-a-page) * [Per-Item Page Overrides](/pages/page-overrides) * [Image Display Controls](/pages/image-display-controls) # Pages Overview Source: https://help.qrtub.com/pages/pages-overview What a Page is, the four steps that turn Pages on for a Collection, and why assigning a Link alone does not produce one A Page is the screen someone sees when they scan a QR code. You build one layout for a Collection, and every Item in that Collection renders that layout with its own field values — so two hundred machines share one design and each shows its own name, serial number and buttons. Because a Page can hold several Destination buttons, one physical code can serve the inspection app, the maintenance system and the operator manual at once, instead of three stickers. ## One Page design per Collection The design is stored once per Collection, as a page template. Items do not each get their own layout; they get their own *data* in the same layout. If you add a button, it appears on every Item in the Collection. That is deliberate — it is what makes a Collection of four hundred Items maintainable. When one Item genuinely needs something different, you can save changes to that Item alone; see [Per-Item Page Overrides](/pages/page-overrides). ## Turning Pages on for a Collection Pages are switched on per Collection, not per Link. 1. **Turn pages on.** In the Collection's settings, open the **Scan behavior** tab, turn on **Show a profile page**, and press **Save changes**. This reveals the Collection's page tab, where you can preview the design and open the Page Editor. Left off, scans pass straight through to a single Destination and there is no page to edit. 2. **Create an Item.** The Page renders an Item's field values, so until a Collection has at least one Item there is nothing for the layout to fill in. 3. **Assign a Link to the Item.** The Link is the URL a QR code encodes. Scanning it resolves to the Item, and the Item's mode decides whether that means a redirect or a Page. 4. **Add Destinations.** In the Page Editor, add ActionLink sections and set each one's Link URL — usually a vendor URL with an Item field folded into it, like `https://cmms.example.com/asset/{{item.serial_number}}`. Switching a Collection between modes later never requires reprinting: the printed code encodes the Link, not the Destination. ## Assigning a Link does not create a Page This is the trap worth knowing before you go looking for a missing page. Assigning a Link only attaches a URL to an Item. If the Collection is set to pass through, its Items keep redirecting no matter how many Links you assign, and no page is ever rendered. The mode is what decides, and an individual Item can override its Collection's setting in either direction — see [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode). ## Everyone who scans sees the same Page A Page is one page. It is not targeted per viewer: an operator, a customer and a contractor scanning the same code all get the same layout, and they self-select from the Destinations on offer. That is usually the point — one code, every option, no wrong sticker. If you need a section to appear only sometimes, that is a separate, explicit mechanism: a condition on the section, evaluated against Item fields, device, time and whether the viewer is a signed-in team member. See [Conditional Visibility](/destinations/conditional-visibility). Without a condition, nothing on the page varies by who is looking. ## Related * [Direct Mode vs. Page Mode](/pages/direct-mode-vs-page-mode) * [The Page Editor Layout](/pages/page-editor-layout) * [Section Types](/pages/section-types) * [Scan Behavior for New Items](/collections/scan-behavior-default) # Previewing a Page Source: https://help.qrtub.com/pages/previewing-a-page The Item selector, the five responsive widths and the Preview toggle — and the four ways an editor preview differs from a real scan The Page Editor renders against real data, not a mockup. The Item selector in the top bar decides which data: * **Base Template** — the default view, with no Item selected. * **Any Item in the Collection** — that Item's actual field values. Switching Item is the fastest way to catch a layout that works for a short name and breaks for a long one, or an ActionLink that quietly disappears because one machine has no serial number. ## Using the Item selector Open the selector and you get a searchable list. Search matches an Item's name, Item ID or description. The arrows either side step to the previous or next Item in the list, which is the efficient way to sweep a Collection looking for layout problems. Two things to know: * **The selector loads the first 100 Items only.** In a larger Collection, search only filters those hundred — an Item beyond them will not appear. To reach one directly, open the editor from that Item instead: its **Page** tab has an **Edit Page** button. * **Selecting an Item turns on override mode**, which changes what saving does. That is the single most important thing to understand before you press Save — see [Per-Item Page Overrides](/pages/page-overrides). **Base Template does not mean placeholder data.** With no Item selected, the canvas still renders against the first Item in the Collection, so what you see is real. Only an empty Collection gets invented sample values ("Sample Machine" and a placeholder image), which exist so that bindings show something rather than blank space. ## Checking widths Five widths are available: **Responsive** (fills the panel), **Mobile** (375px), **Tablet** (768px), **Desktop** (1024px) and **Wide** (1440px). On a narrow screen these collapse into a single dropdown. Mobile is the one that matters most — nearly every scan is a phone — but Desktop and Wide are worth a look if the page's Max Width is set generously, since that is where a page designed on a phone starts to look sparse. ## The Preview toggle The eye button hides the editing chrome: selection outlines, drag handles and drop zones. It also stops rendering sections that are currently hidden, instead of showing them dimmed, so you see close to the finished page. Toggle it back to keep working. ## Four ways a preview is not a scan The preview is honest about data and not about context. These differences are real, and each one has fooled someone: 1. **The preview is always signed in.** A session is always present — yours, or a stand-in if it cannot be read. So any section gated on the viewer being signed in, including the AdminToolbar with its default condition, always appears in the editor and may never appear for a scanner. 2. **Device values come from your own browser.** `device.isMobile`, `device.os` and `device.browser` describe the machine you are editing on. Clicking the Mobile width button changes the canvas width and nothing else — a condition like `device.isMobile` still evaluates as your desktop. 3. **Location is empty.** `request.country`, `request.city` and `request.ip` are all blank in a preview, because there is no real scan behind it. A condition that depends on them will not fire here even when it would fire in the field. 4. **Time is your clock, in the moment.** Time values are computed fresh when the preview loads, so a "weekday business hours" condition shows whatever is true right now. To check any of those four, open the Item's Link on the actual device — and, for the signed-in case, in a browser you are not logged in to. ## The read-only previews outside the editor Two smaller previews render the same page without letting you edit it: the Collection's page tab in settings shows the template in a phone-sized frame, and an Item's **Page** tab shows that Item's page. Both need the Item saved first — a brand-new, unsaved Item shows a "Preview Not Available" message instead. Both carry a button through to the editor. ## Related * [Per-Item Page Overrides](/pages/page-overrides) * [The Page Editor Layout](/pages/page-editor-layout) * [ActionLink: The Destination Button](/pages/action-link) * [Conditional Visibility](/destinations/conditional-visibility) # Section Types Source: https://help.qrtub.com/pages/section-types A map of all 17 sections in the Page Editor palette, grouped by the five categories they appear under, with what each one is for Seventeen section types are available in the Page Editor, grouped into five categories in the **Components** palette. The palette has a search box, so if you know roughly what you want you can type it rather than hunting through categories. This page is a map: what each section is for, and which ones have behavior worth reading about separately. Every section's own fields are listed in the Properties panel when you select it. ## Data Display The sections built around Item and Collection data. This category is expanded by default. | Section | What it is | | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ItemHeader** | Card-style header: image, title, type and subtype, status, chips and a note. The usual top of an Item's page. Its image controls are shared — see [Image Display Controls](/pages/image-display-controls) | | **ActionLink** | The button that sends someone to a Destination. Card-style, with an optional icon and description. See [ActionLink: The Destination Button](/pages/action-link) | | **KeyValue** | A titled card of label-and-value rows. Good for a handful of details | | **SpecGrid** | The same label-and-value pairs laid out as a grid — one or two columns on a phone, up to three on a wider screen | | **Tags** | Inline tag pills, usually bound to the Item's `tags` field | | **ContactInfo** | A contact card: name, title, phone, company with an optional link, address | | **TubInfo** | A card showing the Collection's own name, subtitle, description and image | ## Layout | Section | What it is | | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | **Container** | A wrapper with max-width, padding and background controls. Can hold other sections | | **Card** | A card with an optional title and subtitle, and padding control. Can hold other sections | | **Spacer** | Adds vertical (or horizontal) space between sections, in six sizes | | **AdminToolbar** | A bar of your own buttons pinned to the bottom of the page, hidden from the public by default. See [AdminToolbar](/pages/admin-toolbar) | Container and Card are the two sections that can hold others, so they are how you group things and style the group as a unit. AdminToolbar is always rendered last on the page no matter where it sits in the tree. ## Content | Section | What it is | | ---------- | ------------------------------------------------------------------------------------------------------------------------------- | | **Hero** | A compact hero block: image, a number, title, description, status, a details list and tags — a denser alternative to ItemHeader | | **Text** | A text block with control over the HTML element (paragraph or `h1`–`h6`), size, weight, color role and alignment | | **Banner** | A full-width strip of text for a status or a message | ## Media | Section | What it is | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ImageSection** | A standalone image card. Viewers can zoom the image unless you turn that off. With no image set, it shows a placeholder rather than collapsing. Frame, fit and alignment are covered in [Image Display Controls](/pages/image-display-controls) | ## Interactive | Section | What it is | | ---------- | ------------------------------------------------------------------------------------------------------------ | | **Button** | A simple primary or secondary button. Use ActionLink instead when you want the card-style Destination button | | **Link** | A plain text link. Again, ActionLink is the card-based version | ## Choosing between the three link-shaped sections They are not interchangeable, and the difference is what happens when the URL does not resolve: * **ActionLink** removes itself from the page if its URL depends on a field the Item has not filled in. This is why it is the right choice for Destinations. * **Button** and **Link** do not. A Button with an empty URL renders as a button that does nothing; a Link with an empty URL renders as a link to nowhere. Both are fine for fixed URLs you typed yourself, and a poor choice for URLs built from Item fields. All three support app deep links with a fallback URL or message, so `tel:`, `mailto:` and `myapp://` schemes work in any of them — see [App Links & Fallback URLs](/destinations/app-links). ## What is not a section `Initials` and `ExpandableText` show up inside other sections — the avatar fallback when an Item has no image, and the truncate-with-more control on long descriptions. They are internal pieces, not separate section types, and they are not in the palette. Every section, whatever its type, also carries an optional visibility condition; that is a mechanism of its own, covered in [Conditional Visibility](/destinations/conditional-visibility). ## Related * [ActionLink: The Destination Button](/pages/action-link) * [AdminToolbar](/pages/admin-toolbar) * [Image Display Controls](/pages/image-display-controls) * [The Page Editor Layout](/pages/page-editor-layout) # Archiving and Deleting Batches Source: https://help.qrtub.com/print-batches/archiving-and-deleting Archiving hides a finished batch and is reversible; deleting is permanent and only possible while the batch is still a Draft. Why the difference exists. Archiving and deleting are not two grades of the same action. Archiving hides a batch from the default view and can be undone at any time. Deleting destroys the record permanently and only works on a Draft batch. If a batch has moved past Draft, archiving is your only option. ## Archiving a batch Open the batch and choose **Archive** in the footer, or use the row menu in the Print Batches table. Archived batches: * drop out of the default batch list * come back with the **Show archived** toggle on the Print Batches page, or the **Archived** filter chip in the Print History panel * still appear in a link's own print history, so the record of what a code was printed in is never hidden * keep their CSV, photo, notes, tags and every per-code installation status **Unarchive** is the same button, and it restores the batch to the default view immediately. Archiving works at any status — including Installed — which makes it the normal way to retire a completed run. ## Deleting a batch Deleting is only available while the batch is in **Draft**. In the batch panel the **Delete** button appears in the footer; in the batch list a delete icon appears on hover. Either way you get a confirmation prompt, because there is no undo. Deleting a Draft batch removes: * the batch record * its stored CSV file * its cover photo * every per-code print event belonging to it The links themselves are untouched. Deleting a batch never deletes a Link, an Item, or anything those codes point at — it only discards the record of the run. ## Why deletion stops at Draft Attempt to delete a batch that has reached Printing, Printed or Installed and QRtub refuses with **"Cannot delete a batch that is past draft. Archive it instead."** This is deliberate. Once a batch has been sent to a supplier, its codes may be physically on equipment, and the batch is the only record of what was produced. Losing it would leave stickers in the field with no trace of where they came from. The same protection extends to the links inside the batch: a link that appears in any batch past Draft cannot be hard-deleted. Unassigning it from its Item is still fine — see [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links). Bulk-deleting several batches at once processes them one at a time and stops at the first batch that is past Draft, showing that error. Batches earlier in the selection are already gone by then, so check the statuses before you confirm a bulk delete. If you prepared a run you never sent, leave it as a Draft. That is the only state you can discard cleanly. ## Related * [Batch Status: Draft to Installed](/print-batches/batch-status) * [Finding and Filtering Your Batches](/print-batches/finding-batches) * [Viewing a Link's Print History](/print-batches/link-print-history) # Naming, Tagging and Photographing a Batch Source: https://help.qrtub.com/print-batches/batch-details The four fields that make a batch findable a year later: an inline-renamed name, free-text notes, tag chips, and a cover photo of the finished Tags. A batch arrives with an automatic name like `Print list — Aug 18, 2026`, which tells you nothing in six months. The batch panel gives you four fields to fix that, and all four stay editable at every status — including Installed. ## Renaming a batch Click the batch name at the top of the panel and it becomes an input. **Enter** or clicking away saves; **Escape** cancels. An empty name is ignored, so you cannot accidentally blank it. Names are what the Print Batches search box matches on, so make them searchable rather than decorative: "Depot 2 replacements, March" beats "Batch 14". ## Notes The **Notes** box is free text and saves when you click out of it. Use it for the things you will want and never remember — the supplier, the material and finish, the quote number, the reason for the run, anything odd about the order. Notes are searched alongside the name on the Print Batches page, so a supplier name typed here is enough to find every run you ordered from them. ## Tags Tags are chips, one word or phrase each, for grouping runs that belong together — `depot-2`, `stickers`, `reprint`, `q3`. * Type and press **Enter** to commit a tag. A trailing comma commits it too, so you can type `depot-2, stickers,` straight through. * **Backspace** in an empty tag box removes the last tag. * Click the **x** on a chip to remove that specific tag. * Tags are stored lowercase, and a tag you already have is ignored rather than duplicated. In the Print History panel, every tag in use appears as a filter chip, so tagging is the fastest way to pull up "every reprint" or "everything for depot 2" later. ## Cover photo The **Image** field takes one photo of the finished Tags — the printed sticker on the roll, the engraved plaque, the sign on the wall. Upload any image file; it is stored privately and served back through QRtub rather than from a public URL. Once set, the photo appears as a thumbnail beside the batch in the Print History list, which makes visual identification much faster than reading names. Deleting the batch deletes the photo with it. A photo is a useful stand-in for the Tag detail QRtub does not track — there is no field for material, cost or supplier, so a picture plus a line in the notes is the practical substitute. ## Related * [Finding and Filtering Your Batches](/print-batches/finding-batches) * [Print Batches](/print-batches/overview) * [What Is a Tag?](/tags/what-is-a-tag) # Batch Status: Draft to Installed Source: https://help.qrtub.com/print-batches/batch-status The single status carried by a whole print run — Draft, Printing, Printed, Installed — what each stage unlocks, and why Installed is the end of the line. Every batch carries **one** status covering the entire run: Draft, Printing, Printed or Installed. It describes where the order is, not where any individual sticker ended up. The per-code equivalent is a separate thing entirely — see [Tracking Status Per Code](/print-batches/per-code-status). You change it from the batch detail panel, which shows the current status in the header and one primary button for the next step. ## The four stages | Status | Meaning | | ------------- | ------------------------------------------------------------------------------------------- | | **Draft** | Prepared, not yet sent to the supplier. The only stage where the batch can still be edited. | | **Printing** | With the supplier. | | **Printed** | Received, not yet installed. | | **Installed** | Out in the field. | ## Moving forward Each stage has one named action, and it only ever moves one step: * Draft → Printing: **Finalise and print** * Printing → Printed: **Mark as printed** * Printed → Installed: **Move to installed** You cannot skip a stage. There is no way to take a Draft batch straight to Installed. ## Stepping back Printing and Printed each offer a **Revert to draft** / **Revert to printing** button — one stage back, no further. **Installed is terminal.** There is no revert out of it, and no way to reopen a Installed batch for editing. Advance to Installed once the codes are genuinely out, because that decision is permanent for that batch. Draft has nothing behind it, so it has no revert either. ## What each status changes The status is not just a label — it gates what the batch will let you do: | Only while Draft | Only once Installed | | ------------------------- | ----------------------------------------- | | Add or remove links | The per-code installation tracker appears | | Change the CSV columns | | | Delete the batch outright | | Two more stage-specific behaviors: * **Printing** adds a **Share with Supplier** shortcut, which is simply a download of the stored CSV. * Past Draft, the links inside the batch are protected from deletion — a code may already be printed and stuck to something, so removing it from QRtub would strand the physical item. Name, notes, tags, the cover photo, archiving and the CSV download are available at every stage. ## Related * [Tracking Status Per Code](/print-batches/per-code-status) * [Adding and Removing Links in a Batch](/print-batches/editing-links) * [Archiving and Deleting Batches](/print-batches/archiving-and-deleting) * [Print Batches](/print-batches/overview) # Creating a Print Batch Source: https://help.qrtub.com/print-batches/creating-a-batch Export a print list from a Collection or the Access Links page — and choose between a tracked draft batch and a plain CSV download that records nothing. You create a batch by exporting a print list. The export screen offers two outcomes, and the choice matters: one creates a tracked batch, the other just hands you a CSV file and keeps no record. ## Before you start You need links to print. Every Item with a Link already has one; unassigned links work too, and are the normal starting point for a print-first run where the codes are made before the equipment arrives. ## Exporting from a Collection 1. Open the Collection and select the Items you want. If you select nothing, the export uses whatever your current search, filters and sort produce. 2. Open the **Print Batches** menu and choose **Print list**. 3. Pick your columns (below). 4. Choose **Create draft batch** or **CSV**. ## Exporting from the Access Links page The Access Links page has a **Print List** button in the toolbar and in the row-actions menu. It stays disabled until you select links — this path always works from a selection, or from "select all pages", which hands the server your current filters instead of a list of IDs. On either path, an export built from ticked rows is capped at **5,000 selected rows** — Items from a Collection, links from the Access Links page. Past that, exporting from the current filters instead (leave the Collection selection empty, or use "select all pages" on Access Links) has no such cap, because the server does the selecting. ## Choosing columns The column picker has two groups: * **Item Fields** — the fields defined on the Collection, so a supplier can put a serial number or a location on the label next to the code. * **Link Fields** — **Full URL** (the complete `qrtub.com/...` address), **Short URL** (the path only) and **Active**. Toggle a column with the eye icon, drag to reorder, or use **Show all** / **Hide all**. Full URL is included by default, and it is the one column a supplier genuinely needs — most shops generate the QR image themselves from that value rather than working from image files. One row equals one link, which in practice means one physical piece. Keep that convention and the shop's data merge lines up with your order quantity. ## The two export buttons | Button | What happens | Record kept | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------- | | **Create draft batch** | The CSV is generated and stored server-side, a batch is created in Draft, and you land on **Print Batches** with the new batch open | Yes | | **CSV** | The file downloads to your computer immediately | No | **Create draft batch** does not download anything at that moment. The file is kept with the batch, and you download it whenever you need it — see [The Batch CSV: Downloading and Reprinting](/print-batches/csv-download). **CSV** — labeled "Download CSV without creating a batch" — is a genuinely neutral download. Nothing is tracked, no batch appears in Print Batches, and there is no later record that those codes were ever printed. Use it for a quick look at the data; use the draft batch for anything you are actually sending to a supplier. New batches are named automatically as `Print list — Aug 18, 2026`. Rename it to something you will recognize later, like "Depot 2 replacements, March" — see [Naming, Tagging and Photographing a Batch](/print-batches/batch-details). ## Failure modes worth knowing * **An empty export is rejected.** Exporting with no links selected returns an error rather than an empty batch. * **Tracking can fail silently.** If batch creation fails after the CSV is built, you still get the file — as a download, with a success message. If you asked for a draft batch and got a file download instead of landing on Print Batches, nothing was recorded. Re-export. ## Related * [Batch Status: Draft to Installed](/print-batches/batch-status) * [Editing a Batch's Columns](/print-batches/editing-columns) * [Adding and Removing Links in a Batch](/print-batches/editing-links) * [The Batch CSV: Downloading and Reprinting](/print-batches/csv-download) # The Batch CSV: Downloading and Reprinting Source: https://help.qrtub.com/print-batches/csv-download The exact file that was exported stays with the batch, so a reprint uses the same list — where to download it, what it is named, and when it gets rebuilt. Every tracked batch keeps its CSV. The file is stored with the batch rather than rebuilt each time you ask for it, so downloading it a year later gives you the same list the supplier worked from — not a fresh export that has quietly drifted as Items were added, renamed or deleted. That is the whole point for reprints: order the same fifty replacement plaques and you are ordering the same fifty codes. ## Downloading it There are three places the same download appears: * **The batch list** — hover a row in the Print History panel and click the download icon. It only appears on batches that have a stored file. * **The batch panel footer** — the **CSV** button, available at any status. * **Share with Supplier** — a large button shown while the batch is in Printing. It is the same download, named for the moment you actually need it. The file streams from QRtub itself, so there is no expiring share link to manage and no storage URL to keep track of. The download is named after the batch: a batch called "Depot 2 replacements" downloads as `Depot_2_replacements.csv`. Characters that are awkward in filenames become underscores, very long names are trimmed, and a batch whose name reduces to nothing falls back to `batch.csv`. Renaming the batch changes the filename of subsequent downloads — a good reason to give a run a sensible name before you send it anywhere. ## When the file is rebuilt The stored file is only regenerated by an edit you make while the batch is still a **Draft**: * changing which columns it contains * adding links to it * removing links from it Each of those rewrites the file from current data, replacing the previous version. Once the batch leaves Draft, none of those edits are possible, so the file is frozen for the life of the batch. See [Editing a Batch's Columns](/print-batches/editing-columns) and [Adding and Removing Links in a Batch](/print-batches/editing-links). ## What is in it One row per link, with the columns chosen at export: Full URL, Short URL, Active, plus whichever Item fields you picked. Most suppliers need only the Full URL column — their software generates the QR image from that value. ## When there is no file Two cases where a download is not on offer: * **The batch has no stored CSV.** Batch creation and CSV upload are separate steps, and if the upload failed the batch exists with no file attached. The download button is simply absent, and a direct request returns "No CSV file available for this batch". The fix is to re-export; there is no way to attach a file to an existing batch. * **You exported without tracking.** The **CSV** option on the export dialog downloads a file and creates no batch, so nothing is stored anywhere. That copy on your computer is the only one — see [Creating a Print Batch](/print-batches/creating-a-batch). ## Related * [Creating a Print Batch](/print-batches/creating-a-batch) * [Editing a Batch's Columns](/print-batches/editing-columns) * [Viewing a Link's Print History](/print-batches/link-print-history) * [Preparing Your Print Job](/suppliers/preparing-your-job) # Editing a Batch's Columns Source: https://help.qrtub.com/print-batches/editing-columns Change which Item and Link columns a Draft batch's CSV contains; saving rebuilds the stored file from current data. Locked once the batch leaves Draft. While a batch is still in **Draft** you can change which columns its CSV contains — useful when the supplier comes back asking for a serial number you left out. Saving rebuilds the stored CSV so the file matches the new selection. Open the batch and choose **Edit included columns**. The button only exists while the batch is a Draft. ## What you can pick The **CSV Columns** dialog is the same picker used when you first exported, with two groups: * **Link Fields** — **Full URL**, **Short URL** and **Active**. Full URL is the column a supplier normally needs. * **Item Fields** — the fields defined on the Collection the batch came from. Toggle a column with the eye icon and drag rows to set the column order in the file. Link fields are listed first here, matching the order they appear in the exported CSV. If the batch spans more than one Collection — which happens when you export from the Access Links page rather than from inside a Collection — there is no single field configuration to read, so the picker falls back to the standard fields: name, description, item\_id, tags and destination\_url. Choose **Save** to apply. QRtub saves the selection to the batch and immediately regenerates the stored CSV. ## The regenerated CSV uses current data This is the part worth pausing on. Regenerating rebuilds every row from the Items and links **as they are now**, not as they were at export time. If someone renamed an Item or changed a field after the original export, the new file reflects that change. For a Draft batch that has not been sent anywhere, that is almost always what you want. It also means editing columns is not a way to inspect the original export — once regenerated, the earlier version of the file is gone. ## Why it locks after Draft Advance the batch to Printing and the **Edit included columns** button disappears. Attempting the change anyway is rejected with "Can only edit column config on draft batches." The reason is the same one that protects the rest of the batch: past Draft, the CSV is the record of what the supplier actually received. Silently rewriting it would leave you unable to tell what was produced. If a run genuinely needs different columns, revert the batch to Draft first (see [Batch Status: Draft to Installed](/print-batches/batch-status)) — Printing can step back, Installed cannot. Adding or removing links regenerates the CSV in exactly the same way, under the same Draft-only rule. ## Related * [Adding and Removing Links in a Batch](/print-batches/editing-links) * [The Batch CSV: Downloading and Reprinting](/print-batches/csv-download) * [Creating a Print Batch](/print-batches/creating-a-batch) * [Batch Status: Draft to Installed](/print-batches/batch-status) # Adding and Removing Links in a Batch Source: https://help.qrtub.com/print-batches/editing-links Two ways to change which links a Draft batch contains — from inside the batch, or from the Items and Access Links grids — and the one rule both obey. A Draft batch's contents are not fixed. You can add links to it or take links out, one at a time or in bulk, right up until the batch leaves Draft. Every change regenerates the batch's stored CSV so the file always matches the list. The rule behind both routes below is the same: **links can only be edited on a Draft batch.** ## From inside the batch Open the batch and choose **Edit included links**. The dialog has two tabs: **Current** lists every link in the batch. Filter by link URL, item name or Item ID, tick the links you want gone (or **Select all filtered**), and choose **Remove**. **Add** searches your team's links by link URL, destination, item name or Item ID. Links already in the batch are excluded from the results, so everything you see is genuinely addable. The list shows the first 50 matches with a note like "Showing 50 of 320 available links" — refine the search to reach the rest, or use **Select all (320)** and QRtub adds every match server-side without you paging through them. ## From the Items or Access Links grid Both grids offer **Add to batch...** in the row menu and in the bulk-actions menu. Picking it opens a batch picker that lists **only Draft batches** — a batch past Draft is not offered at all, which is the first place most people notice the rule. If the grid is already filtered to one batch, that batch is hidden from the picker (every row is already in it) and the menu offers a direct add or remove against it instead. From the Items grid the selection is Items, and QRtub resolves each Item to its Link. An Item with no Link is skipped with the warning "Item has no links to add" rather than failing the whole operation. Bulk actions work either from the rows you ticked, or — with "select all pages" — from your current filters, handed to the server as a scope. That avoids sending tens of thousands of IDs from the browser. ## The Draft-only rule, and how it surfaces Once a batch reaches Printing, Printed or Installed, its link list is frozen: * **Edit included links** disappears from the batch panel. * The batch stops appearing in the "Add to batch" picker. * Where a batch is already selected in a grid, the add/remove controls are disabled with the tooltip "Batch is printed — links are locked". * An attempt that reaches the server anyway is refused with "Links can only be edited on a draft batch." To change a Printing or Printed batch, revert it to Draft first. Installed cannot be reverted at all — see [Batch Status: Draft to Installed](/print-batches/batch-status). ## Details worth knowing * **Adding the same link twice is harmless.** A link already in the batch is skipped, never duplicated, and the "added" count reflects only genuinely new links. * **The CSV is rebuilt from current data** after every add or remove, so a renamed Item shows its new name in the regenerated file. * **Removing a link from a batch does not delete it.** The Link, its Item and its destination are untouched; only its membership in this run goes away. * **Link and item counts are recalculated** after every change, so the batch row stays accurate. ## Related * [Editing a Batch's Columns](/print-batches/editing-columns) * [Batch Status: Draft to Installed](/print-batches/batch-status) * [The Batch CSV: Downloading and Reprinting](/print-batches/csv-download) * [Creating a Print Batch](/print-batches/creating-a-batch) # Finding and Filtering Your Batches Source: https://help.qrtub.com/print-batches/finding-batches The Print Batches page: four summary cards, a sortable and searchable batch table, the Show archived toggle, and how to filter Items or Links by the batch they were printed in. Every batch your team has ever created lives on the **Print Batches** page. It opens as a table sorted newest first, with archived batches hidden until you ask for them. ## The four summary cards | Card | What it counts | | ----------------- | ----------------------------------------------------------------- | | **Total Batches** | Batches matching your current search, filters and archived toggle | | **Total Links** | Links across every batch in the team | | **Allocated** | Those links that are assigned to an Item | | **Unallocated** | Those links with no Item attached yet | Worth knowing: only the first card responds to your filters. The three link cards are team-wide totals across every batch, archived ones included, so they will not narrow as you search. A large Unallocated number is normal on a print-first rollout — those are codes printed ahead of the equipment they will represent. ## The table | Column | Contents | | --------------------------- | ---------------------------------------------------------------------------------- | | **Batch Name** | The name, renameable in the batch panel | | **Links** | How many links are in the run | | **Create Date** | When the batch was exported — the default sort, newest first | | **Print Status** | Draft, Printing, Printed or Installed | | **Comment** | The batch's notes | | **Item List** | The Collection the batch was exported from, or a dash for a batch spanning several | | **Allocated / Unallocated** | This batch's own split | Click a row to open the batch panel. Use the column menu to hide columns you never look at — that choice is saved in your browser, so it is per-device rather than per-account, and a different computer starts from the defaults. ## Searching and filtering * **Search** matches the batch name and its notes. Typing a supplier name recorded in the notes finds every run you ordered from them. * **Filters and sorting** work on Batch Name, Links, Create Date, Print Status and Comment. **Item List** and **Allocated / Unallocated** are calculated when the page loads rather than stored, so they cannot be filtered or sorted on. * **Show archived** at the top right brings archived batches into the table. Turning it on resets you to page one. * Results are paged, 25 to a page by default. ## The Print History panel The Access Links page has a second, narrower view of the same batches: a Print History panel with a search box and filter chips for each status, each tag in use, and archived. It shows a batch's cover photo as a thumbnail, which is often the quickest way to recognize a run. Use Print Batches when you want the table, and this panel when you want to skim. ## Filtering Items or Links by batch The reverse question — "what was in that delivery?" — is answered from the batch panel. Its **links** and **items** chips open the Access Links grid and the Items grid filtered to that batch, which is how you get at the Items' own fields rather than the batch's summary. One limit to know: with the Access Links grid filtered by batch, a bulk assign, unassign or delete that acts on "everything matching" cannot use the batch filter as its scope and is rejected with "batch\_id filter is not supported for bulk operations". Tick the specific rows you want instead, and the same bulk actions work normally. ## Related * [Print Batches](/print-batches/overview) * [Archiving and Deleting Batches](/print-batches/archiving-and-deleting) * [Viewing a Link's Print History](/print-batches/link-print-history) * [Naming, Tagging and Photographing a Batch](/print-batches/batch-details) # Viewing a Link's Print History Source: https://help.qrtub.com/print-batches/link-print-history Start from one code and see every batch it has ever appeared in, with the CSV of each run — the per-code view that answers 'has this one been printed before?' The batch pages answer "what was in that order?". This one answers the opposite question: given one code, which orders has it been in? Useful when a plaque needs replacing and you want to know what it was produced with, or when you suspect a code has been printed twice. ## Opening it On the **Access Links** page, the **Print Batch** column summarizes each link's print record — `Printed 3×` with `Last: Mar 9` beneath it. Click that summary to open the Print History panel filtered to that link. A link that has never been in a batch shows a dash and has nothing to open. The panel header repeats the link's slug, where it points, and the Item it is assigned to, so you do not lose track of which code you clicked. ## What you see Every batch the link has appeared in, newest first. Each row carries: * the batch name and its status badge — Draft, Printing, Printed or Installed * who exported it and when * the batch's tags and cover photo * the batch's link and item counts * a download of that batch's stored CSV Archived batches are included here. Archiving hides a batch from the default batch list, but it never hides the fact that a code was printed in it. If the link appears twice, it was printed twice — one row per run. That is exactly how you catch a code that was reprinted without anyone meaning to. ## Setting this link's installation status On a batch that has reached **Installed**, the row shows a small **This link is** control with Printed / Installed / Retired. It sets the installation status of *this one code in that one batch* — not the batch, and not the other codes in it. Rows for batches that have not reached Installed do not show the control, because those codes are not out in the field yet. It is the same value you would set from the batch's installation tracker, reached from the other direction. Use the tracker when you are working through a whole run; use this when you are following a single code. See [Tracking Status Per Code](/print-batches/per-code-status). ## What print history does not tell you * **Nothing about scans.** QRtub records that a code was printed, not that anyone scanned it. "Printed 3×" counts batches, not activity in the field. * **No timeline of changes.** You see each batch's export date, not a per-code history of status changes. * **Nothing about the physical piece.** There is no material, cost or supplier field per code — the batch's notes and cover photo are where that context lives. ## Related * [Tracking Status Per Code](/print-batches/per-code-status) * [The Batch CSV: Downloading and Reprinting](/print-batches/csv-download) * [Finding and Filtering Your Batches](/print-batches/finding-batches) * [Unallocated Links](/links/unallocated-links) # Print Batches Source: https://help.qrtub.com/print-batches/overview What a print batch is: the saved record of one print-list export — the links that were in it, how far the run has progressed, and the CSV the supplier received. When you export a print list, QRtub can keep the run as a **batch**. A batch is the record of one export: which links were in it, the CSV file that went to the supplier, who exported it and when, and how far along the run is. Months later it answers the question a spreadsheet never does — "what was in that order, and where did it go?" Batches live under **Print Batches** in the main navigation. ## What a batch stores | Kept with the batch | Notes | | ------------------------------ | ------------------------------------------------- | | The list of links | One row per link, deduplicated | | The exported CSV | The exact file, stored, not rebuilt on demand | | Name, notes, tags, cover photo | All editable at any time | | Batch status | One value: Draft, Printing, Printed or Installed | | Per-code installation status | One value per link: Printed, Installed or Retired | | Who exported it, and when | Shown on every batch row | ## Two different statuses, two different scopes This trips people up, so it is worth being blunt about it. The two things share vocabulary but count differently: * **Batch status** is a single value for the whole run. One batch, one status. It answers "has this order come back from the supplier yet?" See [Batch Status: Draft to Installed](/print-batches/batch-status). * **Installation status** is one value per code — 500 stickers means 500 independent values. It answers "which of these are actually stuck to something?" See [Tracking Status Per Code](/print-batches/per-code-status). A batch marked Installed does not mean every code in it is installed, and marking every code installed does not move the batch. Neither one changes the other. ## What batches do not record Batches track production runs, not individual individual Tags. There is no per-code record of material, cost, durability, supplier or install location, and no Tag inventory. Scans are not recorded either — QRtub logs that a code was printed, not that it was later scanned. If you need that context today, the batch's notes, tags and cover photo are the place to put it. ## Related * [Creating a Print Batch](/print-batches/creating-a-batch) * [Finding and Filtering Your Batches](/print-batches/finding-batches) * [What Is a Tag?](/tags/what-is-a-tag) * [The Print-First Workflow](/print-first/overview) # Tracking Status Per Code Source: https://help.qrtub.com/print-batches/per-code-status Each code in a batch carries its own Printed / Installed / Retired state — one value per code, independent of the batch's own status — so you can find the ones still in the box. Every code inside a batch has its own installation status: **Printed**, **Installed** or **Retired**. A run of 500 stickers has 500 of these values, moving independently. This is what tells you which sixty codes from a run of five hundred never made it out of the box. Do not confuse this with the batch's own status, which is a single value describing the whole order — see [Batch Status: Draft to Installed](/print-batches/batch-status). A batch marked Installed says the order went out; the per-code statuses say what happened to each piece. Setting one never changes the other. ## Where to find it The installation tracker appears in the batch panel **once the batch's status reaches Installed**. Before that the codes are not physically out yet, so the question does not apply and the tracker is hidden. ## The three states | State | Meaning | | ------------- | ------------------------------------------------------------- | | **Printed** | Produced, not installed yet. Every code starts here. | | **Installed** | Installed and in service. | | **Retired** | No longer in service — damaged, removed, or the item is gone. | Retiring a code is a record, not a deletion. The Link keeps working, and the code stays in the batch and in its own print history. ## Reading the tracker At the top, a segmented bar shows the mix — printed, installed and retired as proportions of the batch — with a count beside each color and the batch total on the right. Only states that actually occur get a segment, so a batch nobody has touched is a single bar. Below it, **Set statuses** expands to the full list. Each row shows the link's slug and, where the link is assigned, the Item's number and name as a link to the Item itself. Codes with nothing attached read "No item linked" — normal for a print-first run where the codes exist before the equipment. **Filter by slug or item** narrows the list as you type, matching the slug, the item name or the Item ID. **Open in grid** opens the Items grid filtered to this batch, which is the better view when you want the Items' own data rather than their installation state. ## Changing statuses **One at a time:** each row has a three-way Printed / Installed / Retired control. Click a state and it saves immediately. **In bulk:** **Mark all as installed** and **Retire all** sit under the tracker. One caution about the bulk buttons: they apply to **every code in the batch**, not to the rows currently showing. The filter box is a view, not a selection — filtering to twelve codes and then clicking **Retire all** retires the whole batch. To act on a subset, use the per-row controls. There is no undo prompt on either bulk action, but nothing is destroyed: run the other bulk button, or set individual rows back, and you are where you were. ## What is not recorded * **No per-code history.** You see a code's current status, not when it changed or who changed it. * **No install location.** There is no field for where a code was fitted. Use the Item it is assigned to for that. * **No scan data.** Installation status is something you set, not something QRtub infers. A code being scanned does not mark it installed. Because of that, the practical workflow is to mark codes as they are fitted, or to bulk-mark the run installed after installation and then retire the handful that never got used. ## Related * [Batch Status: Draft to Installed](/print-batches/batch-status) * [Viewing a Link's Print History](/print-batches/link-print-history) * [Finding and Filtering Your Batches](/print-batches/finding-batches) * [The Print-First Workflow](/print-first/overview) # Adopting an Unknown Code From the Scanner Source: https://help.qrtub.com/print-first/adopting-a-code The scanner's Create & open action: what happens when you adopt a code QRtub doesn't recognize, and the reference photo it captures from the camera When you scan a code the scanner cannot match to any of your Links, it says **"That code isn't linked yet"** and offers **Create & open**. Choosing it adopts that physical code: QRtub mints a new Link for it and opens the new Link's details panel straight away, so you can name it and connect it to an Item while you are still standing in front of the thing. This is how you bring codes you did not print into QRtub — a manufacturer's serial-number sticker, a previous system's asset tag, a hire company's label already stuck to a machine — without relabeling anything. **Early access.** This action, and the scanner it lives in, is built but not switched on yet, so there is no way to open it in the interface today. Email [hi@qrtub.com](mailto:hi@qrtub.com) to ask for access. It is likely to change, and we would rather change it on the strength of what you tell us. ## What Create & open does 1. A new random Link is created in your **currently selected team**, bound to the scanned code. If no team is active you get "Pick an active team first" and nothing is created. 2. The binding is a stored hash of the code's decoded text, so scanning that same physical code again later resolves to the same Link. It is idempotent — a second scan never creates a duplicate. The mechanics of that binding, including what happens to the original decoded text, belong to [Claim-on-Scan](/links/claim-on-scan). 3. The new Link's details panel opens immediately. At this point the Link exists but has nothing attached, so treat the panel as the place to finish the job: give it a destination, or connect it to an Item. The Link you get is a normal random Link. It behaves like any other from then on — you can reassign it, put a Page behind it, include it in a print batch. ## The reference photo If you adopted the code from the **camera**, the scanner grabs a still from the live video at the moment of the scan and attaches it to the new Link as a low-resolution reference photo. It is downscaled to roughly 480 pixels on the long edge and saved as a modest-quality JPEG — enough to recognize which machine, panel or shelf you were looking at, not a documentation photo. Two things worth knowing about it: * **It is best-effort.** The capture happens at scan time but is only uploaded if you actually choose Create & open. If the video was not ready, or the upload fails, adoption still goes ahead — you just get a Link with no photo, and no error. * **The paste and gun-scanner paths never produce one.** There is no camera frame to capture when the code arrived as typed text or from a USB gun scanner, so those adoptions have no photo. If you want the photo, adopt from the camera. The photo is captured at the moment of adoption or not at all — the scanner has no separate "add a photo" step, so if you want one, scan with the camera rather than pasting the code in. ## When to use it, and when not to Use it when the physical code already exists and is staying put: you are adopting the label rather than replacing it. The tradeoff is that the code's meaning now lives in a hash QRtub holds, not in anything readable on the tag, so a code that gets replaced or reprinted by its original owner will no longer match. Where you control the tags, printing QRtub's own Links is the more durable route — see [The Print-First Workflow](/print-first/overview). ## Related * [The In-App QR Scanner](/print-first/scanner) — the camera, paste and gun-scanner inputs this action sits behind * [Claim-on-Scan](/links/claim-on-scan) — the underlying hash-binding mechanism and its idempotency * [The Print-First Workflow](/print-first/overview) — the alternative: printing your own codes up front # The Print-First Workflow Source: https://help.qrtub.com/print-first/overview Why durable tags get printed before the Items they represent exist, and the four-step order that makes a rollout of hundreds practical Most tools assume you create a record, generate a code for it, print that code, and go and stick it on something. That order works for one asset. It falls apart at two hundred. The print-first workflow inverts it: **the codes exist before the records do.** You generate the Links, get them produced in one run, apply them as gear arrives, and connect each one to an Item whenever that part is actually ready. ## Why the usual order does not survive contact with a site Durable identification is made in runs. Photo-anodized aluminum plates are laid up and cut as a sheet. Engraved tags are set up once and produced as a batch. Even ordinary UV-resistant vinyl comes with minimum quantities and a lead time. A CNC machine cutting a sheet of photo-anodized aluminum asset plates, each carrying a QR code, a large asset number and a readable link. The visible plates run in sequence: BOU027, BOU028, BOU029. Above: a run of photo-anodized aluminum plates being cut. The numbers were allocated before any of the equipment they will be fixed to was recorded, because the sheet has to be machined as one job. That has a consequence people usually discover halfway through a rollout: **you physically cannot produce one tag on demand** at any sensible cost. So if your process requires the asset record to exist before the tag can be made, you are stuck choosing between delaying the order until every detail is final, or printing something disposable. Meanwhile the gear itself arrives over weeks. Equipment turns up before anyone has decided what it is called, who owns it, or which system tracks it. Print-first accepts both realities instead of fighting them. ## The four steps **1. Generate the Links first.** Create as many as you need — a hundred, a thousand — before any Items exist. Each one is a real, resolvable URL from the moment it is created. **2. Send the batch to be produced.** Export the list and give it to whoever makes your tags. Plates, engraved labels, weatherproof vinyl, NFC inlays — the medium does not matter, because all it has to carry is a URL. Exporting a print list also records the run as a print batch, so you can tell later what was in that order. **3. Apply tags as gear arrives.** Fix a tag to each asset as it lands, in whatever order things turn up. No decisions required beyond "this tag is now on this machine". **4. Connect when you are ready.** Create the Item and connect it to the tag already on it. This is the only step that needs someone to think, and it is a single action. ## What happens if someone scans a tag early This is the question that usually decides whether the workflow is practical, and the answer matters: **an unconnected code does not 404.** Someone on your team who scans it gets an option to assign it there and then, from their phone. Anyone else gets a neutral branded page rather than an error. So a tag applied on Monday and connected on Friday is not a dead code in the meantime — it is simply not allocated yet. See [Unallocated Links](/links/unallocated-links) for the full behavior. ## Getting the mistakes back Tags get put on the wrong machine. Gear gets sold. A Link can be reassigned to a different Item at any point, so a mistake costs an edit rather than a reprint. The same applies at the end of an asset's life. Deleting an Item does not delete its Link — the Link is released back to your unassigned pool, so a tag already fixed to something in the field keeps working and can be reused. See [Deleting, Unassigning, and Releasing Links](/links/deleting-and-releasing-links). ## Where the codes point A Link can go straight to a single destination, or open a Page with several options. Either way you set it up once for the whole Collection rather than per tag, using a template that fills in each Item's own data: ```text theme={null} https://example.com/assets/{{item.serial_number}} ``` Every tag then resolves to its own asset's record without being configured individually. That is what makes the workflow viable at a few thousand tags rather than a few dozen. Two things to know before you rely on a template across a whole run. Values are inserted **exactly as stored, with no URL-encoding** — a field containing a space or an `&` will break the resulting link, so keep the fields you bind into a URL clean. See [Field Bindings & URL Templates](/destinations/field-bindings) for the full syntax. Because the destination is held by QRtub rather than baked into the code, you can change where every tag points later — a new system, a new URL structure — without touching anything physical. ## Related * [Tips for Print-First Rollouts](/print-first/tips) — numbering, readable text, spares * [Unallocated Links](/links/unallocated-links) — a printable Link with nothing attached yet * [Print Batches](/print-batches/overview) — tracking the run once it is sent to print * [Choosing Your Print Production Method](/suppliers/choosing-a-method) — getting the run actually made # The In-App QR Scanner Source: https://help.qrtub.com/print-first/scanner Scan a code with the camera, a paste, or a USB gun scanner to jump straight to the Link it belongs to — including what it cannot resolve QRtub has a built-in scanner that takes a QR code and tells you which of your Links it is, so you can open that Link's details or follow it to its destination without typing a slug into a search box. It is the tool for the moment you are standing in front of a tag and need to know what it is attached to. **Early access.** The in-app scanner is built but not switched on yet, so there is no way to open it in the interface today. Email [hi@qrtub.com](mailto:hi@qrtub.com) to ask for access. It is likely to change, and we would rather change it on the strength of what you tell us. Everything below describes how it behaves once it is switched on, and is accurate to what is built. ## The three ways it takes input All three converge on the same lookup, so the result screen is identical whichever you use. * **The camera.** A live camera view using the rear-facing camera, decoding QR codes only — not barcodes. It reads continuously with a short delay between attempts, and pauses itself as soon as a code resolves, so holding a tag up to the lens does not fire the same lookup over and over. * **A paste or typed entry.** A text field under the camera view accepts a code pasted or typed in. Useful when you have a URL from an email and no tag in front of you. * **A USB "gun" scanner.** A hardware barcode/QR gun that behaves as a keyboard (HID) types its decoded value plus Enter. The text field is focused automatically, so a gun scan lands in it and submits itself with nothing to click. On a phone the on-screen keyboard is deliberately suppressed for that field, so it does not cover the camera view — the field still accepts paste and gun input. ## What it can resolve The scanner reduces whatever was decoded down to a slug and matches it against your team's Links. It handles: * a full Link URL, for example `https://qrtub.com/r/aBc123` or `https://qrtub.com/ITEM-001` * a bare path, `/r/aBc123` * a bare slug on its own, `aBc123` * a code you have previously adopted from the scanner, matched by a stored hash of its decoded text rather than by slug The lookup runs as you, scoped to your team, so it can only ever return one of your own Links — never another team's. **One known false positive.** For a code that is not a QRtub URL at all, the scanner tries the last segment of its path as a slug. If a third-party code happens to end in a segment that matches one of your custom slugs — a foreign URL ending in `/menu` against your own custom Link `menu` — it will resolve to your Link. The consequence is only ever opening one of your own Links, so it is benign, but it explains an occasional surprising match. The scanner does not keep a scan log. It looks a code up and shows you the result; nothing is recorded about who scanned what or when. ## What you get back When a code resolves, you choose: * **Go to destination** — opens the Link's public URL in a new tab, so the server resolves it exactly as a real scan from a phone would: any conditional rules, device routing and Page or Direct Mode behavior all apply. * **Open access link** — opens that Link's details panel in the app, where you can see and change what it points at, or which Item it belongs to. **Scan another** returns to the live camera without closing the window. When a code resolves to nothing, you get "That code isn't linked yet" and the option to adopt it — see [Adopting an Unknown Code From the Scanner](/print-first/adopting-a-code). ## When the camera will not start The camera path has its own failure modes, each of which shows a specific message rather than a blank view: * **Permission denied** — allow camera access in the browser, then try again. * **No camera found** on the device. * **Camera in use** by another app — close that app first. * **Insecure connection** — camera scanning needs HTTPS. * **Unsupported browser** — the browser cannot do camera scanning at all. In every one of these cases the paste field and a USB gun scanner still work, because neither goes through the camera. ## Related * [Adopting an Unknown Code From the Scanner](/print-first/adopting-a-code) — the "Create & open" action for a code QRtub doesn't recognize * [Claim-on-Scan](/links/claim-on-scan) — the underlying mechanism that binds a third-party code to a Link * [The Print-First Workflow](/print-first/overview) — applying tags before the Items exist * [Unallocated Links](/links/unallocated-links) — what a scan of a not-yet-connected code does # Tips for Print-First Rollouts Source: https://help.qrtub.com/print-first/tips Four decisions that are cheap before the order goes in and expensive afterward: readable text, matching numbers, mixed materials and spare quantity Everything below is decided before the artwork goes to a supplier, and cannot be changed afterward without a second run. None of it is complicated — it is just easy to skip on a first rollout and annoying for years afterward. ## Print the link as readable text under the code Put a short, human-readable version of the URL on the tag, alongside the QR code itself. Codes get scratched, painted over, caked in mud, or scanned in bad light on a cracked screen. When the code will not read, someone can still type six characters into a browser and get to the same place. This costs nothing at print time — it is a line of text in the same artwork — and it is the single most useful thing on a tag that has been in the field for three years. ## Make the tag number and the Link match If the plate reads `HPP021` and the Link is `qrtub.com/hpp021`, there is no second identifier for anyone to remember, mistype, or map back to a spreadsheet. Crews already refer to gear by the number on the tag; matching the Link to that number means the physical label, the URL and the conversation on site are all the same string. Numbered Links exist for exactly this: you claim a range with a prefix and a digit count, and mint against it, so the sequence on the sheet is the sequence in QRtub. See [Numbered Links](/links/numbered-links). If you go the other way and let QRtub generate random slugs, print the slug as text on the tag anyway — otherwise the only way to know which code is which is to scan it. ## Run one numbering scheme across several materials Match the material to the environment, not to the budget — and do not assume that means one material for the whole installation. The tag is only carrying a URL, so what it is made of is a completely separate decision from what it points to. Engraved plates on fixed plant and weatherproof vinyl on hand tools can be consecutive numbers in the same range, produced by different suppliers, in different runs, and still resolve through the same Collection with the same destination template. That means you only have to choose materials for the items you are printing now, not for every item you will ever own. For the material comparison itself, see [Choosing a Tag Type](/tags/choosing-a-tag-type). ## Order more than you need The marginal cost of extra tags inside an existing run is small; setting up a second run three weeks later is not. Order a surplus and keep it in a drawer. Spare tags are not dead weight, because a Link does not need anything attached to exist. Unallocated Links sit in the pool until something turns up to attach them to — a new machine, or a replacement for a tag that got destroyed. The day a plate gets sheared off a machine, the difference between a tag in the drawer and a new order is the difference between five minutes and three weeks. See [Unallocated Links](/links/unallocated-links). A useful rule when scoping the order: count what you have, add what you expect over the next year, then add spares on top of that. The tags do not expire. ## Related * [The Print-First Workflow](/print-first/overview) — the four-step order these tips assume * [Choosing a Tag Type](/tags/choosing-a-tag-type) — material selection by environment and lifespan * [Unallocated Links](/links/unallocated-links) — why spare codes with nothing attached are fine * [Preparing Your Print Job](/suppliers/preparing-your-job) — what to actually hand the supplier # Choosing Your Print Production Method Source: https://help.qrtub.com/suppliers/choosing-a-method Variable data printing versus gang sheets — the two ways a shop produces a batch of unique QR codes, and the one question that tells you which one your job is A batch where every code is different gets produced one of two genuinely different ways: **variable data printing (VDP)**, where the machine images each piece individually and pulls a different value from a data file as the run goes; or a **gang sheet**, where every unique code is laid out in one flattened file first, produced in a single pass, then cut, routed, or engraved apart. Neither is a workaround. Which one applies is decided by the material and the equipment, not by preference. ## VDP versus gang sheets, head to head | | Variable data printing | Gang sheet | | -------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | | **What varies per piece** | The machine changes the code between pieces without stopping | Nothing — one static image per pass | | **When the merge happens** | Live, on press | Once, ahead of time, in design software | | **Who builds the file** | The shop's software, from your data file | You or your designer, before anything is produced | | **Typical materials** | Stickers, labels, paper, vinyl | Photo-anodized aluminum, laser-engraved metal, UV flatbed on rigid panels, screen printing on boards | | **Batch size limit** | Bounded by the run, not the sheet | Bounded by physical sheet or bed size | | **Separation step** | Pieces come off finished | Cut, routed, or laser-cut apart afterward | ## Ask your shop this one question **"Does your equipment image each piece individually and merge live from a data file, or do you need one flattened file with everything already laid out, that gets cut or engraved apart afterward?"** That answer decides everything downstream: * **Live merge** — hand over a data file and let their software do the rest. There may be no artwork assembly for you to do at all. * **Flattened file** — someone has to build the full composite sheet before it goes near the press, engraver, or anodizer. Budget time for that step, and ask what registration or cut marks the artwork needs so the cutting stage lines up with an image that is already permanent. Ask it early. It changes the quote, the lead time, and how many pieces fit in one run. ## What you export is the same either way Whichever flow you are in, QRtub gives you the same two things: a print list CSV (one row per physical piece) and the QR code images as PNGs. Nothing about the export changes. What changes is *who* does the merging and *when* — their software on press, or your design tool beforehand. One caveat worth knowing before you read further: QRtub exports QR codes as PNG only, 1024 × 1024 pixels, black on white. There is no vector export. If a shop needs vector artwork, give them the **Full URL** column from the CSV and let them generate the code themselves — the URL is all a QR generator needs. ## Related * [Variable Data Printing (VDP)](/suppliers/vdp) — how a live per-piece merge works and what the shop needs from you * [Gang Sheets and Composite-Sheet Production](/suppliers/gang-sheets) — building the one flattened file, and the laser-engraving exception * [Preparing Your Print Job](/suppliers/preparing-your-job) — the full handoff checklist * [Print Batches](/print-batches/overview) — tracking a production run once it is sent # Gang Sheets and Composite-Sheet Production Source: https://help.qrtub.com/suppliers/gang-sheets Materials that reproduce one static image per pass — anodized aluminum, laser engraving, UV flatbed, screen printing — need every unique code laid out in one file first, then cut apart Some of the most durable materials for signage and asset tags can only reproduce **one static image per pass**. There is no live merge happening inside the machine at all. So to get a different QR code on every piece, every unique code has to already be sitting in its final position inside **one file** before that pass runs. That file is a gang sheet. The whole sheet is exposed, printed, or engraved in a single pass, and only afterward is it cut, routed, or laser-cut into individual pieces. Materials that work this way include photo-anodized aluminum, laser-engraved metal, UV flatbed printing on rigid panels and acrylic, and screen printing on boards. ## Why the file has to be finished first Photo-anodized aluminum is the clearest illustration: the manufacturer's own guidance is explicit that plates are *imaged first*, with every serial number, barcode, and QR code already baked into the exposure. Cutting is a separate, later step. That has a consequence most people miss — the artwork needs its own registration marks so the cutting tool can line up with an image that is already permanent. Get the marks wrong and you cannot re-image; you have scrap. The same shape applies to laser engraving run in batch mode, UV flatbed on metal or acrylic, and screen printing on rigid boards. Confirm with your shop what registration or cut marks they want on the artwork, and ask early — it is a change to the file, not a setting on the machine. ## Building the composite file: Multiple Records and N-up Assembling a gang sheet is usually done in ordinary design software, not anything specialized. Adobe InDesign's Data Merge has a **Multiple Records** mode built for exactly this. You place a merge-field placeholder once, point it at your data file, and it tiles that placeholder into a grid across the page until the page is full — using your CSV the same way a variable data printing job would, except the output is one flattened file rather than a live merge. A shop running dedicated VDP software has an equivalent step, usually called **N-up** or imposition. Either way, the merge still happens. It just happens once, ahead of time, in a design tool, instead of live on press. Two things to plan for that a VDP job does not force you to think about: * **Sheet and bed size is a hard ceiling.** How many pieces fit on one sheet decides how many passes the job takes and what it costs. Ask before you finalize quantities. * **Bleed, spacing, and kerf.** The cutting, routing, or laser step needs room between pieces. Your designer needs those numbers from the shop, not from a guess. ## The laser-engraving exception Laser engraving can run the *other* way. Some laser software pulls the next serial or code live from a database as each piece is marked, one machine cycle at a time — closer to variable data printing in spirit, even though nothing is printed on a press. In that mode you hand over a data file and skip the composite sheet entirely. Because the same machine can do both, the material does not tell you which you are getting. **Ask which mode your engraver actually runs.** ## What QRtub gives you for this flow The **Full URL** column of an exported print list is the source data for the merge — one row per physical piece. If you or your designer are placing supplied code images instead of generating them during the merge, download the codes as a ZIP; each file is named `qr-code-.png`. One constraint matters more here than anywhere else: QRtub exports PNG only, at 1024 × 1024 pixels, with no vector option. Gang-sheet materials are often large-format, and a raster code enlarged well past its pixel dimensions can blur enough to stop scanning. Where the finished piece is big, do not go looking for a vector export — there isn't one. Give the shop the **Full URL** column and let them generate each code themselves at the exact size their process needs. ## Related * [Choosing Your Print Production Method](/suppliers/choosing-a-method) — the one question that tells you whether your job is a gang sheet * [Variable Data Printing (VDP)](/suppliers/vdp) — the live-merge alternative, and what a press does differently * [QR Code Print Spec: Quiet Zone and Minimum Size](/suppliers/quiet-zone-and-size) — the clear space and minimum size each code on the sheet needs * [Matching QR Codes to Data Rows](/suppliers/matching-codes-to-rows) — pairing each image with the right row before you flatten # Getting and Scanning a Proof Source: https://help.qrtub.com/suppliers/getting-a-proof Why a print proof must show real records rather than a blank template, and why you have to scan the codes with a phone instead of inspecting them on screen Before the full run, ask for a proof of a handful of **real records** — not the blank template — and then **scan the codes with a phone**. Looking at a proof tells you almost nothing about whether the codes are right, because a QR code pointing at the wrong item looks identical to a correct one. ## Ask for real records, not a template A template proof shows you the layout: fonts, colors, dimensions, where the code sits. Useful, and not the risk. The risk is in the merge — whether row 47 of your data file ended up on piece 47. A blank template cannot show you that, because there is nothing merged into it. Ask for three to five actual pieces from the actual data, ideally not consecutive rows, so an off-by-one offset has somewhere to show itself. If the job is a gang sheet, ask for a proof of the composite file with real codes in place, since the whole sheet is produced in one pass and there is no correcting it afterward. ## Scan them, do not look at them This is the part people skip. Open your phone camera, scan each code on the proof, and confirm the destination that opens is the item you expect for that specific piece. A QR code is not human-readable. Two codes for two different items look like the same field of black and white squares. Nothing about a wrong code looks wrong. So a batch built from a shifted column, a mis-sorted CSV, or an image-to-row match that slipped by one comes back looking flawless, scans perfectly, and sends every scan to the wrong asset. Scanning is the only check that tests the thing that actually fails. ## What to confirm on the proof * **The right destination landed on the right piece.** Scan each proof piece and check it against your data file by hand. * **The codes still scan at the real print size**, on the real material, not on a screen or a laser-printed mockup. * **The quiet zone survived.** At least 4 modules of clear space on all four sides, with nothing crossing it — not a border, not a mounting hole, not the edge of a laminate. * **Scanning works at the distance the piece will actually be read from**, and under the lighting it will live in. A code on a plant room door is not the same test as a code on a desk. * **Any printed text near the code is correct too** — including the readable address, if you print one as a fallback. ## Why this is the last cheap moment A data-column mismatch is a well-documented failure mode in variable data printing generally, and it costs almost nothing to catch on a proof of five pieces. Once 500 plaques are anodized, or the gang sheet has been exposed and cut, the fix is a reprint. If the codes point at QRtub Links, a wrong *destination* can be repointed later without reprinting. A wrong *code on the wrong physical piece* cannot — the piece is already attached to the wrong asset, and someone has to go find it. ## Related * [Preparing Your Print Job](/suppliers/preparing-your-job) — the handoff this proof is checking * [Matching QR Codes to Data Rows](/suppliers/matching-codes-to-rows) — the step a bad proof usually points back to * [When a Supplier Redraws Your File](/suppliers/when-a-supplier-redraws) — why the proof may not look like the file you sent * [Print Batches](/print-batches/overview) — tracking the run once the proof is approved # Matching QR Codes to Data Rows Source: https://help.qrtub.com/suppliers/matching-codes-to-rows Pairing a downloaded qr-code-.png with its row in an exported print list, and why neither the Short URL nor Full URL column is an exact string match for the filename Matching is manual, and it turns on the slug. Every downloaded QR code image is named after its Link's slug — a Link at `qrtub.com/r/aBc12` downloads as `qr-code-aBc12.png`. The same slug appears at the end of the **Short URL** and **Full URL** columns of an exported print list. Match on the slug. The catch: **neither column is a byte-for-byte match for the filename.** Whoever does the matching has to strip a prefix first. ## What each column actually contains | Column | Value for a random Link | Value for a numbered or custom Link | | ------------- | --------------------------- | ----------------------------------- | | Filename | `qr-code-aBc12.png` | `qr-code-cra0042.png` | | **Short URL** | `/r/aBc12` | `/cra0042` | | **Full URL** | `https://qrtub.com/r/aBc12` | `https://qrtub.com/cra0042` | So: * **Short URL** carries a leading slash, and for random Links an additional `/r/` prefix. Numbered and custom Links get the leading slash but no `/r/`. * **Full URL** carries the protocol and domain on top of that. * The filename carries the bare slug plus `qr-code-` and `.png`. Nothing in QRtub exports the bare slug as its own column today. Any tool doing the match — a Canva Bulk Create sheet, an Illustrator or Photoshop script, a few lines of Python, or a spreadsheet formula — has to do the transformation itself. ## The transformation Going from a filename to a slug is the simpler direction: drop the `qr-code-` prefix and the `.png` extension. Going the other way, from a column to a slug, means stripping the protocol and domain if you started from **Full URL**, then the leading `/`, then `r/` if it is there. In a spreadsheet, the usual approach is a formula that takes everything after the last `/` in the URL — that handles both Link types in one pass, because the slug is always the final path segment. Whichever direction you go, build the key once in a helper column and match on that, rather than eyeballing hundreds of rows. ## Why the mismatch matters Because a wrong match is invisible. Two codes are the same size, the same colors, the same visual noise. A batch where rows and images got offset by one produces plaques that look flawless and send every scan to the wrong item. There is no error, no warning, and no way to tell by looking. That is why the check happens on a proof, with a phone, and not on screen. ## The shortcut: skip the images entirely If your shop's software can render QR codes directly from text — many variable data printing toolchains can — hand over the CSV alone and let them generate each code from the **Full URL** column. No image files, no filenames, no matching step, and nothing to get offset by one. Ask whether they can. It removes the single most error-prone part of the handoff. ## Related * [Preparing Your Print Job](/suppliers/preparing-your-job) — the full handoff this step sits inside * [Getting and Scanning a Proof](/suppliers/getting-a-proof) — where a bad match gets caught * [Downloading QR Codes](/bulk-links/downloading-qr-codes) — how the PNG and ZIP filenames are built * [What a Slug Is](/links/what-a-slug-is) — the identifier both the filename and the URL are built from # Preparing Your Print Job Source: https://help.qrtub.com/suppliers/preparing-your-job The five-item orientation checklist for handing a QR code batch to a supplier — production method, spec, data file, code images, matching, and proof A supplier running a batch of unique QR codes needs five things settled before the run: which production method applies, the design spec, the data file, the code images (sometimes), and a way to match one to the other. Then a proof. This page is the map; each item has its own page with the detail. ## 1. Which production method applies Ask the shop: does their equipment image each piece individually and merge live from a data file, or do they need one flattened file with everything laid out, cut apart afterward? The first is variable data printing. The second is a gang sheet, and it means someone has to build the composite file before anything is produced. Settle this first, because it decides whether you owe them a data file or a finished sheet. See [Choosing Your Print Production Method](/suppliers/choosing-a-method). ## 2. The design spec Give them a reference image of the finished piece plus the details a picture cannot carry: final dimensions, bleed, and — specific to a QR code — the minimum size and the clear space around it. Mark the quiet zone boundary explicitly, not just where the code sits. A shop rebuilding your artwork needs to know where that boundary is. See [QR Code Print Spec: Quiet Zone and Minimum Size](/suppliers/quiet-zone-and-size). ## 3. The data file Export a print list from QRtub: open the Links you want, choose **Print List**, select your columns, and download the CSV. Include the **Full URL** column at minimum, plus any Item fields you want printed alongside the code. One row in that file is one physical piece. That is the whole convention, and every print toolchain expects it. ## 4. The code images — sometimes If the shop's software renders QR codes directly from the **Full URL** text, you do not need image files at all; the CSV alone is the handoff. If they place supplied images instead, download the codes as a ZIP from the same Links view. QRtub exports PNG only — 1024 × 1024 pixels, black on white, with no vector option and no size or color control. Where vector genuinely matters, hand over the **Full URL** column and let the shop generate the codes themselves. ## 5. Matching, then a proof Each downloaded file is named `qr-code-.png`, and neither URL column in the CSV is a byte-for-byte match for that filename — whoever matches has to strip a prefix. See [Matching QR Codes to Data Rows](/suppliers/matching-codes-to-rows). Then ask for a proof of a handful of real records, not a blank template, and **scan** the codes rather than looking at them. A code pointing at the wrong item looks identical to a correct one. See [Getting and Scanning a Proof](/suppliers/getting-a-proof). Expect the shop to rebuild your artwork in their own software along the way. That is normal practice, not a warning sign — see [When a Supplier Redraws Your File](/suppliers/when-a-supplier-redraws). ## Related * [Choosing Your Print Production Method](/suppliers/choosing-a-method) — the entry point for this group * [Matching QR Codes to Data Rows](/suppliers/matching-codes-to-rows) — filename-to-CSV pairing * [Getting and Scanning a Proof](/suppliers/getting-a-proof) — the last cheap place to catch a mismatch * [Print Batches](/print-batches/overview) — tracking the run once it is sent to print # QRtub QR Code Standards Source: https://help.qrtub.com/suppliers/qr-code-standards What to choose when you export a code and why: SVG for print, Q error correction, a 4-module quiet zone, black on white, and the logo beside the code rather than inside it. A QR code on a plate is a decision you make once and live with for years. These are the settings QRtub recommends, and the reasoning behind each — so you can put them on a print spec and defend them. ## The standards, in short | Setting | Our standard | Because | | ---------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | Format | **SVG** for anything printed. PNG only for screens | Vector scales to any plate size with no soft edges | | Error correction | **Q** for printed tags. **H** if it will be damaged or obscured. **M** for screens, never **L** | Choose by where the code is going. The size difference between levels is small and unpredictable | | Quiet zone | **4 modules**, with nothing crossing it | Below 4 the scanner can lose the code's edges | | Printed size | **20–25 mm minimum**, larger with scanning distance | Below that, focus and material texture start to decide the outcome | | Color | **Black on white** | Contrast is what a camera actually reads | | Logo | **Beside the code, never inside it** | A logo inside spends the damage budget on decoration | | The address | **Printed as readable text nearby** | It can be typed when the code is unreadable | ## Format: SVG unless it is going on a screen SVG is vector, so the same file prints at 20 mm on a tool tag or 400 mm on a plant room door with identical edges. It is the right choice for every supplier handoff. PNG is a fixed grid of pixels — QRtub exports it at 1024 × 1024. That is roughly 87 mm at 300 dpi, which is fine for a tag or a sticker and not enough for a sign. Enlarge a PNG well past that and the module edges soften until the code stops decoding. Use PNG for a web page, an email, a slide. ## Error correction: Q for print, and do not shop on size Error correction is how much of the code can be destroyed and still scan — roughly 7% at L, 15% at M, 25% at Q and 30% at H. Those figures come from the QR standard and do not change. | Level | Survives | Use it for | | ----- | --------- | --------------------------------------------------------------------------------------------- | | L | \~7% | Nothing. The weakest level, and it rarely buys anything | | M | \~15% | A code on a screen, or in a document | | **Q** | **\~25%** | **Anything printed. This is our standard** | | H | \~30% | Codes that will be scratched, painted over, partly covered, or scanned from a few centimeters | **Choose by where the code is going, not by how big the code comes out.** Raising the level can add modules, which at a fixed physical size makes each module smaller — but how much, or whether at all, is genuinely unpredictable. It depends on the length of the address, whether the slug happens to contain digits, and which domain the code encodes. The same Link produces a different code on `qrtub.com` than on the shorter `qrt.au`. That unpredictability is the reason not to optimize here. The difference between levels is at most a step or two of module count, which a phone camera does not notice at a sane printed size — while the difference between 15% and 25% damage tolerance is what decides whether a scratched plate still works in year eight. **Take Q and spend your attention on size and material instead**, which are where printed codes actually fail. Error correction protects against damage, not against a code printed too small. A pristine 10 mm code at H still will not scan reliably. Size first, then error correction. ## Quiet zone: 4 modules, and nothing crosses it The blank border around the code is what the scanner uses to find its edges. Four modules on all four sides, and nothing in it — no logo, no border, no text, no mounting hole, no laminate edge. QRtub exports a 4-module margin, so a placed file already carries its quiet zone. **What it cannot do is protect it.** Anything your layout puts inside that border — a rule, a rivet, a trim edge — takes the clear space back. Mark the boundary on the spec, not just the code's position. Full detail in [Quiet Zone and Minimum Size](/suppliers/quiet-zone-and-size). ## Color: black on white Black on white is the only combination guaranteed to work, because a camera reads contrast rather than color. QRtub exports black on white and does not offer brand colors — a code in your brand's mid-tone on a light background can look right and fail in poor light. ### Transparent background The export offers a transparent background as a deliberate choice. It removes the QR code's background so it can be placed over other artwork — a colored substrate, an anodized plate, an existing label design. Take it only when you control what ends up behind the code, because **the white background is not decoration. It is the quiet zone, made physical.** Turning it off hands responsibility for both contrast and clear space to whoever places the artwork, and the failure arrives late: a transparent code looks correct on a white screen and disappears into a dark plate. ## Where the logo goes **Beside the code, above it, or below it — not inside it.** A logo in the middle of a QR code works by destroying modules and relying on error correction to reconstruct them. That is the same budget you provisioned for grit, scratches and a decade of UV. Spending it on branding means the code leaves the shop already partly consumed, and the first real damage is the damage that breaks it. There is no reserved space in the middle of a QR code. Unlike the three corner squares, the center is live data. A logo outside the code costs nothing, can be considerably larger, and stays legible from further away than the code can be scanned from anyway. On a plate with room for both, that is the better design as well as the more durable one. ## Print the address as text too Put the Link's address in readable text near the code — `qrtub.com/cra0042tl` under a code, or `CRA0042TL` as the plate's own number. It is the fallback when the code is unreadable, and with a numbered Link it does double duty: the plate number and the web address are the same string, so there is one identifier instead of two and nothing to map back to a spreadsheet. See [Choosing a Link Type](/links/choosing-a-link-type). ## Related * [Quiet Zone and Minimum Size](/suppliers/quiet-zone-and-size) — the two numbers for a print spec * [Downloading QR Codes](/bulk-links/downloading-qr-codes) — the export dialog and what it produces * [Preparing Your Print Job](/suppliers/preparing-your-job) — where these standards go in the handoff * [Choosing a Tag Type](/tags/choosing-a-tag-type) — what to print them on # QR Code Print Spec: Quiet Zone and Minimum Size Source: https://help.qrtub.com/suppliers/quiet-zone-and-size The 4-module quiet zone nothing may cross, the 20-25mm practical minimum for phone scanning, and why the exported margin is not the quiet zone Two numbers belong on every print spec you hand a shop: a quiet zone of at least **4 modules** on all four sides, and a printed size of at least about **20–25 mm (roughly 1 inch)** square. Both are about whether a phone camera can decode the code at all — and both fail silently, producing a piece that looks perfect and does not scan. ## The quiet zone: 4 modules, and nothing may cross it A module is one of the small squares the code is built from. The quiet zone is blank space on all four sides, at least 4 modules wide, and the scanner uses it to find the code's edges. Nothing can cross into it. Not a logo, not a border, not a line of text, not a **mounting hole**, not the **edge of a laminate** or an overlay film. Any of those can stop the code decoding while leaving artwork that looks entirely correct to the eye. Mark the quiet zone on your spec as a boundary, not an afterthought — the shop needs to know where the clear space ends, not only where the code sits. This matters most on small tags, where a fixing hole and the code are competing for the same few millimeters. ### The exported margin is the quiet zone — protect it Every code QRtub exports carries a **4-module** margin, SVG and PNG alike, which is what print specs ask for. So a placed file arrives with its quiet zone intact. What the file cannot do is defend it. A rule, a border, a fixing hole or a trim edge that sits inside that margin takes the clear space back, and the code still looks correct. Mark the boundary on your spec rather than assuming the built-in margin survives layout. ## Minimum size: about 20–25 mm As a rule of thumb, do not print a code smaller than about 20–25 mm square if it needs to be reliably scanned by a phone camera. Below that, the modules get small enough that camera focus, print resolution, and material texture start to matter more than the code itself. Scanning distance pushes that number up, not down. A code on a plant room door read from two meters away needs to be much larger than one on a handheld tool. ## Size, format, and what error correction can and cannot do QRtub exports **SVG or PNG**, black on white, with the error-correction level of your choice. Two practical consequences for a print spec. **Use SVG for anything printed.** It is vector, so one file covers a 20 mm tool tag and a 400 mm door sign with identical edges. PNG is a fixed 1024 × 1024 pixels — roughly 87 mm at 300 dpi, which is comfortable for a tag or a sticker, tight for a plaque, and not enough for a sign. Enlarged well past that, a PNG's module edges soften enough to stop scanning. If a shop only has the PNG and needs it larger, give them the **Full URL** column from your print list and let them regenerate at press size — that is normal practice, not a workaround. **Error correction is a real lever now, but it is not a substitute for size.** For a piece that will live outdoors, be laminated, or get scratched, raise the level — **Q** for most printed tags and **H** where the code will be damaged or partly covered. For QRtub's short addresses the step up is often free, so this usually costs nothing; see [QR Code Standards](/suppliers/qr-code-standards). What it cannot do is rescue a code that was printed too small. A pristine 10 mm code at H still will not scan reliably, because the failure there is the camera resolving individual modules, not missing data. Size first, then error correction — and print the address in readable text nearby either way, so someone can type it when the code is beyond saving. ## Related * [Preparing Your Print Job](/suppliers/preparing-your-job) — where this spec fits in the full handoff * [When a Supplier Redraws Your File](/suppliers/when-a-supplier-redraws) — why they will often regenerate the code themselves * [Downloading QR Codes](/bulk-links/downloading-qr-codes) — the export dialog and what the files contain * [QR Code Standards](/suppliers/qr-code-standards) — every setting we recommend, and why # Variable Data Printing (VDP) Source: https://help.qrtub.com/suppliers/vdp How a digital press images each piece individually and merges a different QR code from your data file live at print time, and what to hand a shop running it Variable data printing is a live, per-piece merge: a digital press (laser or inkjet) images every unit individually, so the shop's software can pull a different value from a data file for each one as the run goes. The code changes from one piece to the next without stopping the press. This is the flow for stickers, labels, and anything printed on paper or vinyl at volume. ## Every VDP job is two things merged at print time **A template.** Your design, with the parts that stay identical on every piece — logo, border, headings, any fixed text — and a marked region for the part that changes. The template is built once. **A data file.** One row per physical piece, one column per thing that varies. At minimum that means the destination address for each piece, and, if the shop is placing supplied images rather than generating codes itself, a reference to the matching code image. The merge itself happens inside the press's software during the run. Nothing is flattened in advance, which is why a VDP job is not bounded by sheet size the way a gang sheet is — a run of 5,000 is the same job shape as a run of 50. ## What to give a VDP shop Export a print list from QRtub: open the Links you want to print, choose **Print List**, select your columns, and download the CSV. One row in that file is one physical piece — that is the convention every VDP toolchain expects. Include the **Full URL** column. A shop with live variable-data software can render each QR code directly from that text, with no image files involved at all. If that is your situation, you do not need to download the code images and you do not need to solve the filename-matching problem; the CSV alone is the whole handoff. Add any Item fields you want printed alongside the code — name, description, tags — as extra columns. ## When they do want the images Some shops place a supplied PNG rather than generating the code themselves. Download the codes as a ZIP from the same Links view. Every file is named `qr-code-.png`, and matching each one to its CSV row takes a small string transformation, because neither URL column is a byte-for-byte match for the filename. ## Limits worth stating up front QRtub exports PNG only — 1024 × 1024 pixels, black on white. There is no vector option, no size or color control, and no exposed error-correction setting. For most VDP work on labels and stickers that is fine, because the pieces are small. Where it matters, the answer is not a different export format: hand the shop the **Full URL** column and let them generate the code at the size and format their press wants. Also worth confirming before the run: which column the shop is treating as the variable field. A column mismatch produces a batch where every code scans perfectly and points at the wrong item. It looks correct until someone scans it. ## Related * [Choosing Your Print Production Method](/suppliers/choosing-a-method) — the question that tells you whether your job is VDP at all * [Matching QR Codes to Data Rows](/suppliers/matching-codes-to-rows) — pairing `qr-code-.png` with its CSV row * [Getting and Scanning a Proof](/suppliers/getting-a-proof) — catching a column mismatch while it is still cheap # When a Supplier Redraws Your File Source: https://help.qrtub.com/suppliers/when-a-supplier-redraws Why a supplier rebuilding your artwork in their own software is standard practice rather than a warning sign, and what they actually need from you when they do Expect the shop to rebuild your design in their own software rather than use your file as-is — even if you built it properly in Illustrator, even if you exported exactly what they asked for. This is standard practice, not a sign that something went wrong with your file. ## Why they do it **Color separation for their press.** Your file's colors have to be converted to whatever their specific press, ink set, or substrate actually uses. That conversion is easier and more predictable in a file their software built than in an imported one, and it is their job to get right, not yours. **Regenerating the QR code at the correct size and quiet zone.** Shops routinely prefer to generate the code from your data rather than trust a pasted-in image, so it renders at exactly the right module size and with the exact clear space their process needs. A supplied PNG has a fixed pixel size and only a two-module margin; a code they generate has neither limitation. **Their production files are built for their equipment.** Imposition, registration marks, bleed, and cut paths are set up the way their machines expect. Rebuilding is often faster than adapting someone else's file to that. ## What they need from you when they rebuild Not your source file, necessarily. What they need is: * **A visual and a spec to rebuild from** — a reference image of the finished piece, plus final dimensions, bleed, and the QR code's minimum size and quiet zone. * **The data file**, one row per physical piece. * **The QR code for each piece, or just its URL** — the **Full URL** column is enough if their software renders codes itself. * **Confirmation of which column is which.** This is the one that gets skipped, and it is the one that causes wrong-destination batches. ## A worked example One QRtub customer designed a plaque in Illustrator, then sent it to a supplier for a batch of unique codes. The shop rebuilt the design in their own software. What they actually needed from the customer was the visual and spec to rebuild from, the data file with one row per plaque, the QR code or URL for each, and confirmation of which column was which. The Illustrator file itself was reference material, not production artwork. The shop sent back a proof before running the full batch. The customer scanned the codes on that proof rather than just looking at them — which is the only way to catch a code that renders perfectly and points at the wrong item. ## When it *is* worth a question Redrawing is normal. Two things are still worth confirming after they do it: * That the quiet zone survived the rebuild. Nothing should cross it, including a mounting hole or a laminate edge. * That the code on each piece matches the intended row. Ask for a proof of real records and scan them. ## Related * [Getting and Scanning a Proof](/suppliers/getting-a-proof) — what to ask for and what to check * [QR Code Print Spec: Quiet Zone and Minimum Size](/suppliers/quiet-zone-and-size) — the spec numbers a rebuild has to preserve * [Preparing Your Print Job](/suppliers/preparing-your-job) — the full list of what to hand over # Choosing a Tag Type Source: https://help.qrtub.com/tags/choosing-a-tag-type General industry reference comparing stickers, plaques, signs, large format and NFC by cost, lifespan and use case — guidance, not data QRtub stores Pick the material by the environment and the time the code needs to survive, then check the budget — not the other way around. A sticker that fails in eighteen months on a machine you expected to keep for ten years costs far more to replace than the plaque you skipped, because replacing it means a site visit, not a print job. Everything on this page is general industry reference to help you brief a supplier. **QRtub does not store any of it.** There is no field for material, cost or durability against an individual code — see [What Is a Tag?](/tags/what-is-a-tag) for what is and isn't recorded. ## Common tag types | Type | Typical cost each | Typical lifespan | Where it fits | | ----------------------------------- | ----------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | **Vinyl stickers** | $0.50 – $5 | 1–3 years indoors, 3–5 years weatherproof outdoors | General equipment, short-to-medium rollouts. 2×2" to 6×6" are the common sizes | | **Metal plaques** | $20 – $100 | 10+ years | Permanent installations, high-value equipment. Stainless steel or aluminum, engraved or photo-anodized | | **Rigid signs** | $50 – $500 | 5–15 years | Facility signage, wayfinding, fixed locations. Aluminum, acrylic, PVC, coroplast | | **Real-estate and yard signs** | $50 – $300 | 6 months – 2 years | Property listings, directional signs. 18×24" to 24×36" are common | | **Billboards and large format** | $500 – $5,000+ | 6 months – 3 years, depending on material and weather | Campaigns, public information | | **Printed ads, postcards, inserts** | $0.10 – $2 | Single use | Direct mail, publications, campaigns | | **NFC inlays and chips** | $1 – $10 | 5–10 years | Products, tap-to-scan installations. Can encode the same Link as the printed code, so both routes lead to the same place | Costs vary enormously by quantity, region and finish. Treat the columns above as an order of magnitude for scoping, not a quote. ## Choose by environment * **Indoors, clean** — standard vinyl. * **Outdoors, weather** — UV-resistant weatherproof vinyl, or metal. * **Harsh: salt water, constant wash-down, abrasion, chemicals, heat** — engraved or photo-anodized metal. A boat or a wash bay is a different specification from a generator sitting in a yard. * **Embedded in or attached to a product** — a sticker or an NFC inlay, depending on whether the code needs to be visible. ## Choose by how long it has to last * **Under a year** — vinyl stickers, printed material. * **One to five years** — weatherproof vinyl, rigid signs. * **Ten years and up** — metal plaques, engraved signs. Anything expected to outlive the software it currently points at belongs here, since the Link is what stays fixed and the destination is what changes. ## Choose by what it goes on * **Equipment and plant** — stickers for consumables and light gear, metal plaques for anything with a service life. * **Facilities and rooms** — rigid signs and plaques. * **Marketing** — large format, printed ads, postcards. * **Products** — stickers, NFC inlays. ## Mixing grades in one rollout You can run several different materials against a single numbering scheme. The tag only carries a URL, so what it is made of is a separate decision from what it points to: the plaques on your fixed plant and the stickers on your hand tools can be consecutive numbers in the same range, produced by different suppliers, in different runs, and still resolve through the same Collection with the same destination template. That is worth planning for before the first order, because it means you do not have to decide the material for every future item now — only for the items you are printing now. ## Related * [What Is a Tag?](/tags/what-is-a-tag) — Tags as an entity, and what QRtub records about it * [Tips for Print-First Rollouts](/print-first/tips) — practical advice on numbering, spares and readable text * [Choosing Your Print Production Method](/suppliers/choosing-a-method) — which of the two production flows your chosen material needs * [Gang Sheets and Composite-Sheet Production](/suppliers/gang-sheets) — why the durable materials above are produced differently # What Is a Tag? Source: https://help.qrtub.com/tags/what-is-a-tag A Tag is the physical material a QR code is displayed on — a third entity alongside the Item and the Link, and the one QRtub tracks least A **Tag** is the physical thing a QR code sits on: a vinyl sticker, an engraved metal plaque, a rigid sign, a billboard, a real-estate sign, a printed ad, an NFC inlay. Most tools stop at generating the digital pattern. QRtub treats the material that pattern gets printed on as its own thing, because it has its own cost and its own lifespan — usually a longer one than the equipment it is attached to. ## The three entities QRtub keeps three separate things in view whenever codes go into the physical world: | Entity | What it is | Example | | -------- | ------------------------------------------- | ------------------------------------------------------------ | | **Item** | The thing being represented | An excavator, a fire extinguisher, a meeting room, a product | | **Link** | The QRtub-managed URL — the digital pattern | `qrtub.com/r/x5fgd` | | **Tag** | The physical material displaying the code | A vinyl sticker, a metal plaque, a billboard, an NFC inlay | Keeping them separate is what makes the rest of QRtub work. The Link is not baked into the Tag, so a plaque outlives whatever system it currently points at. The Item is not baked into the Link, so a Tag can be moved to a different machine with an edit instead of a reprint. And the Tag is not baked into either, so a damaged sticker can be replaced with a new one carrying the same Link, and the Item connection survives — the new sticker just has to encode the same URL. ## What QRtub tracks today **Production runs, not individual pieces.** Exporting a print list from a Collection creates a **print batch** — a record of exactly which links went to the supplier, what stage the run is at (Draft → Printing → Printed → Installed), and a per-code Printed / Installed / Retired status so you can find the sixty stickers out of five hundred that never left the box. A batch carries a name, notes, tags and a photo of the finished Tags, keeps the CSV that was sent, and can be archived when the run is done. That is the whole of what is recorded about the physical layer. See [Print Batches](/print-batches/overview). ## What is not tracked There is no record of what an individual QR code is printed *on*. No material type, no cost, no durability rating, no installation location, and no per-piece inventory. These are planned, not built: * Tags as a stored entity, with a type and material per piece * Tag Templates — reusable design templates for production * Tag inventory and cost reporting * A replacement workflow that supersedes one Tag with another * Suppliers — a program of vetted producers you can order through So production runs are tracked; individual Tags are not. Today you produce Tags through whichever supplier you already use, and any cost or material record lives in your own accounting, not in QRtub. ## Related * [Choosing a Tag Type](/tags/choosing-a-tag-type) — comparing materials by environment, lifespan and cost * [Print Batches](/print-batches/overview) — what is actually recorded about a production run * [The Print-First Workflow](/print-first/overview) — why the Tags usually get made before the Items exist * [Choosing Your Print Production Method](/suppliers/choosing-a-method) — getting a batch of unique codes actually produced # Accepting a Team Invitation Source: https://help.qrtub.com/team/accept-invitation How to join a team you have been invited to — the Accept button in the notification bell if you already have an account, or automatic joining on first sign-in if you don't How you join depends on whether you had a QRtub account when the invitation was sent. ## If you already had a QRtub account Sign in and click the **bell icon** in the top right of the dashboard. The invitation is listed there — "You've been invited to join \[team] as \[role]" — with **Accept** and **Decline** buttons. Click **Accept**. You are now a member, and the team appears in the team switcher at the top of the left sidebar; switch to it to see its Collections and Items. **The link in the invitation email does not accept for you.** It signs you in and drops you on the Team page, which is a good place to be — but you still have to open the bell and click **Accept**. Until you do, the team is not in your switcher and you cannot see any of its data. This kind of invitation does not expire. It waits in the bell until you accept it or the team's owner removes it. ## If you did not have an account The email you received has a link that creates your account. Click it, set a password when prompted, and you are dropped into the dashboard already in the team — a message confirms you have been added. There is no Accept button in this path, because clicking the link is the acceptance. Two things follow from that. QRtub does not create a personal "your name's Team" for you, because you were invited into an existing one; and the invitation expires **7 days** after it was sent. If the link no longer works, ask the person who invited you to hit **Resend** — that issues a fresh link and a fresh 7 days. If you already have several teams, note that the joining happens on your first dashboard load after signing in, so give it a moment before deciding the invitation failed. ## Declining **Decline does not currently work.** The button sends a request the server rejects, so you get an error message and the invitation stays where it is. Ignoring an invitation has the same practical effect: an invitation you never accept never gives anyone access to anything, and the team's owner can remove the pending row from their end. If you want it gone from your bell, ask them to remove you from the team's member list. ## If you can't find the invitation * **Nothing in the bell?** You may have been invited under a different email address than the one you signed in with. Invitations are matched on the exact address. * **Team not in the switcher after accepting?** Reload the dashboard, then check the switcher again. * **Told you were added but you never got an email?** Ask the owner to resend it and to check the address they used. ## Related * [Inviting Team Members](/team/invite-members) * [Managing Pending Invitations](/team/pending-invitations) * [Switching Between Teams](/team/switching-teams) * [Team Roles](/team/roles) # Creating a Team Source: https://help.qrtub.com/team/create-a-team Making a second team from the sidebar switcher — the name and slug fields, the logo file rules, and what a brand-new team starts with Open the team switcher at the top of the left sidebar and choose **Create Team**. Fill in the form, click **Create Team**, and QRtub switches you into the new team straight away. You already have one team without doing this: signing up creates a team named after your email address, with you as its owner. Create a second one when you genuinely need separate data — a different business entity, a client whose Items must not mix with yours, or a separate subscription. ## The form | Field | What it does | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Team Name** | Required. What you and your members see in the switcher and page headers. Change it later at any time. | | **Team Slug** | Required. Filled in automatically from the name — lowercased, spaces turned into hyphens. You can overwrite it; once you type in it, it stops following the name. | | **Team Logo** | Optional. Shown in the switcher and on the Team page. | The slug accepts lowercase letters, numbers and hyphens only. Anything else is rejected with "Slug can only contain lowercase letters, numbers, and hyphens." Slugs are unique across all of QRtub, not just your teams, so a common one may be taken by someone you will never meet. If it is, you get "That team slug is already taken" and nothing is created — add a word and try again. The slug is an identifier, not an address: it is not part of any Link URL or dashboard address. See [Team Settings](/team/team-settings). A logo must be a JPEG, PNG, GIF or WebP file up to 50 MB. SVG files are rejected. The logo is uploaded after the team itself is created, so if the image fails, you still have a team — just re-add the logo from Team Settings. ## What you get You become the team's owner immediately, with every owner-only power in it: settings, invitations, member removal, and the Subscription section. Nothing else carries over from your other teams. A new team starts genuinely empty — no Collections, no Items, no Links, no reserved numbered patterns, no print batches. Your first step is normally [creating a Collection](/collections/creating-a-collection). Billing is per team. A new team has no subscription of its own, and the plan on your existing team does not extend to it. ## Related * [Team Overview](/team/overview) * [Team Settings](/team/team-settings) * [Switching Between Teams](/team/switching-teams) * [Creating a Collection](/collections/creating-a-collection) # Inviting Team Members Source: https://help.qrtub.com/team/invite-members Sending an invitation from the owner-only Invite Member card, the two different paths for people who already have a QRtub account and people who don't, and the daily invite limit On the **Team** page, use the **Invite Member** card: type the person's email address, pick their role, and click **Invite**. Only the team's owner sees that card, and the server refuses invitations from anyone else. You do not need a paid plan to invite people. Inviting is not gated on having a subscription. ## The email field Type the full email address. The dropdown that appears under the field matches **exact addresses only** — typing `jo` will never suggest `joanne@example.com`. That is deliberate: partial matching would let anyone probe which email addresses have QRtub accounts. People already on the team are left out of the suggestions entirely. You do not have to wait for a suggestion. Type the whole address and click **Invite** either way. Pick the role in the dropdown next to the button. **Editor** is the default and is what almost everyone should get. **Owner** is also offered, but it only sets a label — it does not give that person any owner powers. See [Team Roles](/team/roles). ## What happens next depends on the invitee **If they already have a QRtub account,** a pending membership is created. They appear in your members table immediately with the status **Pending**, and they get an email plus a notification in the bell at the top right of their dashboard. They join when they accept it there. This kind of invitation does not expire. **If they don't have an account,** QRtub creates an email invitation instead. It appears in the **Pending Invitations** card, expires in 7 days, and the email they receive contains a link that creates their account. They join the team automatically on their first sign-in — no accept step. See [Accepting a Team Invitation](/team/accept-invitation). The two lists are separate, and this trips people up: someone who already had an account shows up in the **members table** as Pending, not in the Pending Invitations card. The **Pending** tile at the top of the page counts email invitations only. ## When an invitation is refused * **"This user is already a member of this team."** They are already on the team, or already have a pending membership. Check the members table for their row. * **An email invitation already exists for that address.** QRtub sends the invitation again and restarts its 7-day window rather than creating a duplicate. * **"Too many requests. Please try again later."** Each team can send **50 invitations per day**. The message includes how long to wait. The count is per team, not per person, and it covers both kinds of invitation. ## Related * [Managing Pending Invitations](/team/pending-invitations) * [Accepting a Team Invitation](/team/accept-invitation) * [Team Roles](/team/roles) * [Removing Team Members](/team/remove-members) # Leaving a Team Source: https://help.qrtub.com/team/leave-a-team Leaving from the Danger Zone as a member, and what happens when the owner leaves — the automatic ownership handover, who it picks, and why a sole owner cannot leave at all Open the **Team** page and click **Leave Team** in the **Danger Zone** at the bottom. Confirm, and your membership is gone. QRtub moves you to another of your teams, or shows "No team selected" if that was your only one. Leaving is immediate and there is no undo. You lose access to that team's Collections, Items, Links, Pages and print batches, and getting back in requires a fresh invitation from the owner. Nothing you created is deleted — it all belongs to the team. ## If you are the team's owner An owner cannot simply walk away: a team always has to have an owner. Clicking **Leave Team** as the owner opens a dialog headed **Transfer ownership and leave**, which lists the team's active members and then tells you plainly that "the first active member will be selected as the new owner." **You do not get to choose from that list.** The names are shown for information; the handover always goes to the first member listed, which is the most recently added active member of the team. If a specific person should end up owning the team, make sure they are the newest member before you leave — removing other members, or re-inviting the intended person so their membership is the newest, are the only levers you have. Confirming does three things in order: the chosen member becomes the team's owner, your own role drops to Editor, and then your membership is deleted. Because they happen in sequence, a failure at the last step leaves you still in the team but no longer its owner — reload the Team page to see where you ended up before trying again. This is the only place ownership ever changes. There is no transfer-ownership button or screen anywhere else in QRtub. ## If you are the only member You get "You are the only member. You cannot leave." and nothing happens. A team with one member has nobody to hand ownership to. There is no delete-team option in the dashboard either, so a team you no longer want simply stays in your switcher. If it holds a subscription you want to stop, deal with that in the team's Subscription section rather than by trying to remove the team. ## What happens to the team after you leave The team keeps everything: its Collections, Items, Links, printed codes and members. Its subscription belongs to the team, not to you, so it stays attached and the new owner is the one who now sees the Subscription section on the Team page. Members who joined at your invitation are unaffected. Printed QR codes keep resolving exactly as before — nothing about a scan depends on who owns the team. ## Related * [Team Roles](/team/roles) * [Removing Team Members](/team/remove-members) * [Switching Between Teams](/team/switching-teams) * [Team Overview](/team/overview) # Team Overview Source: https://help.qrtub.com/team/overview The container that owns every Collection, Item, Link and print batch in QRtub — where teams come from, who can belong to several, and what only the owner controls A team is the container that owns your QRtub data. Collections, Items, Links, reserved numbered patterns, page templates, print batches and Tags all belong to a team, not to a person — which is why two people on the same team see exactly the same Collections and the same pool of Links. Every team also holds its own member list and its own subscription. Nothing is shared between two teams: a Link created in one team cannot be assigned to an Item in another, and a plan bought for one team does not cover the other. ## Where your team came from Most teams are created one of three ways: * **Automatically, at signup.** Creating a QRtub account creates a team named after your email address — `jane's Team` for `jane@example.com` — with you as its owner. * **By you, deliberately.** Use **Create Team** in the team switcher at the top of the left sidebar. See [Creating a Team](/team/create-a-team). * **By someone inviting you.** If you signed up by clicking a team invitation, no personal team is created for you at all. You land straight in the team that invited you. You can belong to as many teams as you are invited to, and switch between them at any time. Only memberships you have actually accepted count — see [Switching Between Teams](/team/switching-teams). ## What only the owner can do Every team has exactly one owner: the person recorded as its owner, which starts out as whoever created it. The owner is the only member who can change the team's name, slug or logo, invite or remove members, manage pending invitations, see the Subscription section, or delete a Collection or an Item. Everything else — creating Collections and Items, editing fields, creating, editing and deleting Links, building Pages, running print batches, importing and exporting CSVs — every member can do. Details in [Team Roles](/team/roles). ## The Team page Open **Team** in the left sidebar. The header shows the team's logo, name, slug and member count, with an **Edit** button for the owner. Below it, four tiles: **Members** (accepted members), **Pending** (invitations sent to people without a QRtub account), **Owners** and the date the team was created. Then the members table — **People with access**, **Last Seen**, **Status** and **Access** — followed by a **Danger Zone** with the **Leave Team** button. One thing worth knowing about that table: the **Last Seen** column does not track activity. It shows when the person joined the team, or when they were invited if they have not joined yet. Nobody's last sign-in or last edit is recorded anywhere in QRtub. ## Related * [Switching Between Teams](/team/switching-teams) * [Team Roles](/team/roles) * [Inviting Team Members](/team/invite-members) * [What Is a Collection?](/collections/overview) # Managing Pending Invitations Source: https://help.qrtub.com/team/pending-invitations The Pending Invitations card — resending or revoking an emailed invitation, the 7-day expiry, and where the other kind of pending invite hides The **Pending Invitations** card on the Team page lists invitations you have sent, with the person's email address, the role they were invited as, and the date the invitation expires. Each row has two buttons: **Resend** and **Revoke**. The card is visible to the team's owner only. ## What this card does and does not list It lists **only invitations sent to email addresses that have no QRtub account yet**. Those people have nothing to accept in-app — the emailed link is the whole mechanism, so it needs managing from here. Anyone you invited who **already had a QRtub account** is not in this card. They are in the members table below it, with the status **Pending**, and they join by accepting the notification in their own dashboard. To cancel that kind of invitation, remove their row from the members table — see [Removing Team Members](/team/remove-members). The **Pending** tile at the top of the page counts this card's rows only, so it can read `0` while a Pending row still sits in the members table. ## Resend **Resend** emails the person a fresh sign-in link and pushes the expiry out to 7 days from now. Use it when the original never arrived, went to spam, or has expired. Resending is limited to **10 times per hour for any one invitation**. Past that, the button reports too many requests and tells you when to try again. Resending never creates a second invitation — there is only ever one per email address per team. ## Revoke **Revoke** asks you to confirm, then deletes the invitation. The link already sitting in that person's inbox stops adding them to your team. Nothing else is affected: if they had already created a QRtub account from the link and joined, revoking a later invitation does not remove them — that is a member removal instead. You can re-invite the same address afterwards from the **Invite Member** card. ## Expiry Email invitations expire **7 days** after they are sent, and again 7 days after each resend. Expired invitations are not cleaned up automatically. They stay in this card with a past expiry date until you revoke them, so the list is worth a scan occasionally. An expired invitation no longer adds anyone to the team, even if they click the old link and create an account — but a **Resend** brings it back to life with a new 7-day window, so you never need to delete and recreate it. ## Related * [Inviting Team Members](/team/invite-members) * [Accepting a Team Invitation](/team/accept-invitation) * [Removing Team Members](/team/remove-members) * [Team Overview](/team/overview) # Removing Team Members Source: https://help.qrtub.com/team/remove-members Taking someone off a team from the members table, one at a time or in bulk — what they lose immediately, and what stays behind with the team On the **Team** page, find the person in the members table and click the **X** at the right of their row. Confirm, and they are off the team. To remove several people at once, tick the checkbox at the left of each row, then use **Remove Selected** below the table. The checkbox in the header row selects everyone. Only the team's owner can remove members. Other members see the table without the X or the bulk button, and the removal is refused at the server too, so there is no way around it. ## Be careful with the owner's own row The owner's row has no **X**, so it cannot be removed one row at a time. Its checkbox is still selectable, though — and the header checkbox that selects everyone includes it. Removing the owner's own row that way does go through, and it is not something you want: the team stops appearing in your team switcher, because a team only shows up for people with an active membership in it. Select rows individually rather than using the select-all checkbox. An owner who wants to hand the team over should use **Leave Team** in the Danger Zone instead, which transfers ownership on the way out — see [Leaving a Team](/team/leave-a-team). ## What removal actually does Access ends immediately. The team disappears from their team switcher, and its Collections, Items, Links, Pages, print batches and Tags are no longer reachable by them. **Nothing they made is deleted.** Everything in QRtub belongs to the team, not to the person who created it, so the Items they added, the Links they generated and the Pages they built all stay exactly where they are. Removing someone is never a way to clean up data. Their QRtub account itself is untouched, along with any other teams they belong to. If your team was their only one, they will see "No team selected" and can create a team of their own. ## Removing a pending member A row with the status **Pending** is someone who was invited but has not accepted yet. Removing that row cancels the invitation. They keep no access, and the notification in their bell stops working. That only applies to people who already had a QRtub account. An invitation sent to an address with no account is not in this table at all — cancel those with **Revoke** in the Pending Invitations card. See [Managing Pending Invitations](/team/pending-invitations). ## Adding someone back There is no undo and no archive of past members. To bring someone back, invite them again from the **Invite Member** card; they will need to accept the new invitation. Their old role is not remembered, so pick it again. ## Related * [Inviting Team Members](/team/invite-members) * [Managing Pending Invitations](/team/pending-invitations) * [Leaving a Team](/team/leave-a-team) * [Team Roles](/team/roles) # Team Roles Source: https://help.qrtub.com/team/roles The two roles QRtub has — Owner and Editor — what genuinely differs between them, why there is no read-only role, and why the Owner label alone grants nothing QRtub has two roles: **Owner** and **Editor**. Editor is the default for anyone you invite. There is no third role, and no way to change a member's role after the fact — the role is chosen when the invitation is sent. ## There is no read-only role You cannot give someone view-only access. Every member you invite can create Collections and Items, edit any Item's fields, create and edit Links, build and change Pages, and run print batches. If a person should not be able to change your data, do not add them to the team. The word "viewer" appears nowhere in the product, and an Editor cannot be restricted to a single Collection either — team membership is all-or-nothing across everything the team owns. ## What the owner can do that an Editor cannot Permissions key off one thing: whether you are **the team's owner**, the single person recorded as owning the team. That is the only distinction the system actually enforces: | Action | Owner | Editor | | ------------------------------------------------------------------------------------------------ | ----- | ------ | | Edit team name, slug, logo | Yes | No | | Invite members, resend or revoke invitations | Yes | No | | Remove members | Yes | No | | See the team's Subscription section | Yes | No | | Delete a Collection, or delete an Item | Yes | No | | Everything else — Collections, Items, fields, Links, Pages, print batches, CSV import and export | Yes | Yes | Deleting a Tag Template or a Print Batch is owner-only too. Deleting a **Link** is not — any member can delete or release Links, including ones somebody else created. **An Editor's delete of a Collection or an Item fails quietly.** The confirmation goes through and you may see no error at all, but the record is still there when the list reloads. If a member reports that deletes "don't stick," this is why: they are not the owner. Ask the owner to do it. ## Why the Owner label grants nothing The invite form lets you pick **Owner** as the role for the person you are inviting. That choice only sets the word shown in the members table's **Access** column. It does not make them the team's owner and it grants none of the powers in the table above — they still see the Team page as a non-owner, with no Edit button, no invite card and no Subscription section. The team's real owner changes in exactly one place: when the current owner leaves the team, which hands ownership to another member as part of leaving. There is no separate transfer-ownership screen. See [Leaving a Team](/team/leave-a-team). ## Related * [Inviting Team Members](/team/invite-members) * [Leaving a Team](/team/leave-a-team) * [Removing Team Members](/team/remove-members) * [Team Overview](/team/overview) # Switching Between Teams Source: https://help.qrtub.com/team/switching-teams Using the team switcher at the top of the sidebar, which teams appear in it, and why the team you land in can differ from one browser or device to the next Switch teams from the **team switcher** at the very top of the left sidebar — the button showing your current team's logo and name. Click it, pick a team from the list, and QRtub reloads everything for that team. Picking a different team returns you to the dashboard home first. That is deliberate: the Collection, Item or batch you were looking at belongs to the team you just left, so there is nothing to show it in the new one. ## What switching changes Everything in the dashboard is scoped to the current team. After a switch, the Collections in the sidebar, the Items inside them, the Links pool, print batches, Tags, reserved numbered patterns and search results are all the new team's. Your account, your profile and your password are not team-scoped and do not change. The team's own settings follow too — the Team page now shows the new team's members, and if you are its owner, its Subscription section. ## Which teams appear in the list Only teams where you have an accepted, active membership. Three consequences worth knowing: * **A team that has invited you does not appear until you accept.** If someone says they added you and the team is not in your switcher, the invitation is still waiting in the notification bell — see [Accepting a Team Invitation](/team/accept-invitation). * **A team you left, or were removed from, disappears immediately.** If it was your current team, QRtub quietly moves you to another one. * **If you belong to no teams at all**, the dashboard shows "No team selected. Please select or create a team from the sidebar." ## Why you sometimes land in a different team Your current team is remembered in the browser you are using, not on your account. Sign in from a different browser, a different device, or a private window, and QRtub has nothing remembered — it opens the most recently created team you belong to. So the same account can sit in team A on your laptop and team B on your phone. If something is missing, check the switcher before anything else: it is far more often the wrong team than missing data. This also means clearing your browser data resets which team you open in. ## Other places teams are listed **Create Team** sits at the bottom of the switcher dropdown. When the sidebar is collapsed, the switcher shrinks to the team logo alone — hover it to see the team name. Your **Profile** page also lists every team you belong to, and separately lists the teams you own alongside their subscription status, with a **Manage** button that switches to that team and opens its Team page. ## Related * [Team Overview](/team/overview) * [Creating a Team](/team/create-a-team) * [Accepting a Team Invitation](/team/accept-invitation) * [Leaving a Team](/team/leave-a-team) # Team Settings Source: https://help.qrtub.com/team/team-settings Renaming a team, changing its slug and replacing its logo from the owner-only Edit panel — including the slug that rewrites itself while you type a new name Open **Team** in the sidebar and click **Edit** next to the team name. A **Team Settings** panel opens with three fields — Team Name, Team Slug and Team Logo — plus **Save Changes** and **Cancel**. Nothing is saved until you click **Save Changes**. The **Edit** button only appears for the team's owner. Other members see the Team page without it, and the change is refused at the server as well, so there is no way around it. If you need a different person editing the team, ownership has to move — see [Leaving a Team](/team/leave-a-team). ## Renaming the team Type a new name and save. The name updates everywhere at once: the switcher, the Team page header, your Profile's team list, and the invitation emails sent from then on. Existing Links, Collections and printed QR codes are unaffected — nothing physical depends on the team's name. **Watch the slug field while you rename.** As long as you have not touched the slug yourself, it rewrites itself from the name on every keystroke. Rename "Northside Plumbing" to "Northside Plumbing Group" and the slug silently becomes `northside-plumbing-group`. If you want the slug to stay as it is, retype it in the slug field before saving — editing it once stops it from following the name for the rest of that editing session. ## The slug The slug accepts lowercase letters, numbers and hyphens only; anything else is rejected on save. It has to be unique across all of QRtub, so a save can come back with "That team slug is already taken" — pick another and save again. What the slug is actually for is narrower than it looks. It is a readable identifier shown under the team name on the Team page and beside each team on your Profile page. It is **not** part of any Link address, any scanned URL, or any dashboard address, so changing it cannot break a printed QR code or a saved bookmark. ## The logo Upload a JPEG, PNG, GIF or WebP file up to 50 MB. SVG files are rejected. The logo appears in the team switcher and in the Team page header; teams without one show the first letter of the team name instead. Uploading a new file replaces the old one on save. ## What is not here There is no delete-team button anywhere in the dashboard, and no control for changing another member's role. Member roles are fixed when you invite them ([Team Roles](/team/roles)), and the only thing that moves ownership is an owner leaving the team. Owners also see a **Subscription** section above the settings panel on the same page. That covers the team's plan rather than its identity, and it is visible to the owner only. ## Related * [Team Overview](/team/overview) * [Creating a Team](/team/create-a-team) * [Team Roles](/team/roles) * [Leaving a Team](/team/leave-a-team) # Search Everything Source: https://help.qrtub.com/workspace/search-everything The global search in the dashboard top bar: which four things it matches, the six-results-per-section cap, how recent searches are stored, and why it spans every team you belong to Search Everything is the magnifying glass in the top bar of the dashboard. One box searches your Collections, Items, Links and Pages at the same time, and clicking a result takes you straight to it. It is built for finding one specific thing fast — not for building a filtered list, which is what the search and filter controls inside a Collection are for. Click the magnifying glass to open the panel, then start typing. Press `Escape`, click the X, or click outside the panel to close it. The magnifying glass only appears at tablet and desktop widths; on a narrow phone screen it is not in the top bar, so navigate through the sidebar instead. There is no keyboard shortcut to open it. ## What it matches Results are grouped into up to four sections, and each section matches a specific piece of text: | Section | What it matches | | ----------- | --------------------------------------------------------------------------- | | Collections | The Collection name | | Items | The Item's name **or** its Item ID | | Links | The slug in the Link's address — not the name of the Item attached to it | | Pages | Same as Links, for Links whose Collection has Page Mode as its scan default | In the app the Collections section is labeled "Tub" and the Links section "Access Link" — older names for the same two things. The Links/Pages split is decided by the Collection's default scan behavior, not by the individual Item. A Link in a Page Mode Collection is filed under Pages even if that particular Item is set to Direct Mode. Both kinds of result show the Item's name when one is attached, but the search itself only looks at the address, so typing an Item name will not surface its Link — search the Items section for that and open the Item. Nothing else is searched. Descriptions, tags, custom field values, Destinations, Tags and print batches, Page templates and teammate names are all outside this search. ## Matching is a plain "contains", from one character Searching begins as soon as you have typed one character, after a short pause of about a third of a second so it is not re-querying on every keystroke. Matching is case-insensitive and matches anywhere in the text, so `cav` finds `Excavator`. It is not fuzzy and it is not word-by-word. The whole phrase you typed is matched as a single run of text, so `excavator north` only finds text containing exactly that sequence, and a misspelling finds nothing. These characters are removed and replaced with a space before the search runs: `%` `_` `,` `(` `)` `\` `*`. That means an Item ID like `AB_100` cannot be found by typing `AB_100` — type `AB` or `100` instead. ## Six results per section, and no results page Each section shows at most six results. There is no pagination and no "see all results" screen — if what you want is not in the first six, type more of it. Links and Pages are drawn from the same batch of matching addresses, so a query matching a lot of Links can leave the Pages section shorter than the six it would otherwise show. The Filter button beside the box narrows results to one section: All, Collections, Items, Links or Pages. Choosing a section with no matches shows "No results" rather than falling back to the others. The filter resets to All every time you reopen the panel. ## It covers every team you belong to Search Everything is scoped to all the teams your account is a member of, not just the team you currently have selected. If you belong to two teams, one query returns results from both, and the results are not labeled by team — Item rows show the Collection name, which is usually enough to tell them apart. If your account belongs to no team, the search returns nothing. Clicking a result opens it: a Collection opens its page, an Item opens its Collection with that Item selected, and a Link or Page opens its public address in a new browser tab. ## Recent searches, and the one failure to know about Before you type, the panel lists your recent searches — up to six terms, most recent first. They are stored in the browser you are using, so they do not follow you to another device and no teammate sees them. A term is only remembered when you click through to a result; typing something and closing the panel saves nothing. **Clear All** deletes the list. If the search request itself fails, the panel shows "No results for …" — exactly what a genuine miss looks like. If you are confident something should have matched, close the panel and search again before concluding the record is missing. ## Related * [Item ID](/items/item-id) — the identifier the Items section matches on * [What a Slug Is](/links/what-a-slug-is) — the part of a Link's address that Links and Pages match on * [Scan Behavior for New Items](/collections/scan-behavior-default) — the Collection setting that decides whether a Link is filed under Links or Pages * [Key Concepts](/key-concepts) — one sentence each on Collection, Item, Link and Page