Need your GoodBarber Custom Code to behave differently for a logged-in user — show premium content, greet a member by name, hide a section from anonymous visitors? Whether you wrote that code yourself or generated it with the AI Extension Builder, it asks the App API who's connected through gb.user.getCurrent(). But the back-office preview has no real login, so for Membership apps that call always lands in the error path. This guide explains how the current user behaves in the preview for every app type, and gives you a copy-paste way to test as a logged-in member.
A lot of Custom Code needs to know who is using the app right now: showing premium content, greeting members by name, hiding a section from anonymous visitors, adapting a checkout. The GoodBarber App API gives you the current user through gb.user.getCurrent().
And Custom Code isn't only something you write by hand anymore. With GoodBarber's AI Extension Builder, you describe the section you want in plain language and the assistant generates the extension for you — code that plugs straight into the same GoodBarber App API. Hand-written or AI-generated, it calls gb.user.getCurrent() the same way, and you test it the same way. So this guide applies whether you typed the code or prompted for it.
But here's the catch every developer eventually hits: inside the back-office preview, there is no logged-in user. The preview is just a render of your app — there's no login screen, no session, nothing to authenticate against.
For most app types, GoodBarber quietly works around this for you, so testing "as a logged-in user" just works. For the Membership extension, it doesn't — and that's on purpose. This article walks through how the current user behaves in the preview for each app type, and gives you a simple, copy-paste way to test the trickiest case: a logged-in member.
A quick refresher: gb.user.getCurrent()
The GoodBarber App API lets your Custom Code ask "who is using the app right now?" through one method:
(user) => {
// A user is logged in.
// `user` is a GBUser object — read its attributes here.
console.log(user.email);
},
(error) => {
// No user is logged in.
console.log(`Response status: ${error.code}`);
console.log(`Response message: ${error.message}`);
}
);
It takes two callbacks: a success callback (called with a GBUser object when someone is logged in) and an error callback (called when nobody is logged in). It's callback-based — it does not return a value or a Promise.
The GBUser object changes shape per app type
The GBUser model carries an api_version property that tells you which kind of app produced it:
api_version | App type |
|---|---|
1 | Content app + Authentication extension |
2 | eCommerce app |
3 | Content app + Membership extension |
The list of attributes depends on that version. For a Membership app (api_version: 3), a GBUser looks like this:
id: 123,
api_version: 3,
login: "member@example.com",
email: "member@example.com",
username: "John Doe",
firstname: "John",
lastname: "Doe",
picture_url: "https://example.com/picture.jpg",
access_levels: ["premium"] // 👈 the key field for Membership
}
The access_levels array is what makes Membership special: it lists the access levels the user currently holds. That's almost always what your Custom Code branches on ("does this user have premium? then show the bonus content").
In practice, your code reads access_levels to decide what to show:
(user) => {
if (user.access_levels.includes("premium")) {
console.log("Member has premium — show the premium content");
} else {
console.log("Logged in, but no premium — show the upgrade prompt");
}
},
(error) => {
console.log("Nobody logged in — show the login prompt");
}
);
Keep this in mind — it's exactly this code the mock below will feed.
How the current user behaves in the preview
The preview in the back office is a sandbox. It renders your app, but it has no login mechanism — there's no way to actually authenticate a real user inside it.
To keep development comfortable anyway, GoodBarber injects a fake user for some app types so that getCurrent() returns something you can work with:
| App type | In the preview, getCurrent()… |
|---|---|
Authentication add-on (api_version: 1) | ✅ Returns a fake user automatically — your success callback fires. |
eCommerce app (api_version: 2) | ✅ Returns a fake customer automatically — your success callback fires. |
Membership extension (api_version: 3) | ❌ Returns nothing — your error callback fires with "There's no user logged in the app." |
So if your app uses Authentication or eCommerce, you can test your logged-in logic in the preview right away — a fake user is handed to you for free, no setup needed.
If your app uses the Membership extension, it's different: no fake user is injected. If your success callback never fires in the preview and you keep landing in the error path, that's expected — there simply is no current user to return, and unlike the other two app types, none is faked for you.
The rest of this article focuses on that Membership case, because it's the one that needs a bit of work. You have two ways to handle it.
Option 1 — Test in the MyGoodBarber app (real conditions)
The most faithful way to test is to run your app inside the MyGoodBarber app (available on iOS and Android). It loads your real app, with the real login flow and the real backend. You log in as an actual member, and getCurrent() returns your real GBUser with your real access_levels.
Use this when you want to validate the whole flow end-to-end before publishing. It's the closest thing to production.
The downside: it's a slower feedback loop. You can't iterate on a CSS tweak or a conditional branch as fast as you can in the preview. That's where Option 2 comes in.
Option 2 — Mock getCurrent() in the preview
For fast iteration, you can temporarily replace gb.user.getCurrent with your own version that hands back a fake member of your choosing. Your real logic stays exactly the same — your Custom Code still calls gb.user.getCurrent(success, error) like normal. You're only swapping out what the method does while you're testing.
Step 1 — Drop in the mock at the top of your code
Add this block at the very beginning of your Custom Code's JavaScript, before any call to getCurrent():
const PREVIEW_TESTING = true;
if (PREVIEW_TESTING && typeof gb !== "undefined" && gb.user) {
gb.user.getCurrent = function (successCallback, errorCallback) {
const fakeUser = {
id: "123",
api_version: 3,
login: "member@example.com",
email: "member@example.com",
username: "Test Member",
firstname: "Test",
lastname: "Member",
picture_url: "",
access_levels: ["premium"] // 👈 change this to test different cases
};
successCallback(fakeUser);
};
}
💡 "premium" is just an example. Use the real access level identifiers configured in your app — otherwise your conditions won't match anything.You might wonder: can't my code just detect the preview and mock only there? Unfortunately, no — there's no reliable signal exposed to your Custom Code that says "this is the preview" (gb.platform() returns "web" in the preview, exactly like a real PWA in production), and from getCurrent alone the preview is indistinguishable from a genuinely logged-out user (both hit the error callback). That's why we use a flag you flip by hand: it's explicit, and it can't be triggered by accident in production.
That's it. From now on, anywhere in your Custom Code where you call:
…your onUserFound callback receives the fake member above — exactly as if a real premium member were logged in. You don't change your business logic at all; you only added the mock block on top.
Step 2 — Test the cases that matter
The whole point of Membership code is reacting to different users. Just edit the mock to cover each scenario:
A subscribed member (has access levels):
A logged-in user with no subscription:
Several access levels at once:
Nobody logged in at all — here you mock the error path instead of the success one:
errorCallback({ code: 1, message: "There's no user logged in the app." });
};
Flip between these to make sure your Custom Code behaves correctly in every state — not just the happy path.
Step 3 (optional) — Mock gb.membership.getAccessLevels() too
Some Membership code reads access levels through the dedicated Membership method rather than the user object:
(access_levels) => { console.log(access_levels); },
(error) => { console.log(error.message); }
);
If you use it, mock it the same way:
gb.membership.getAccessLevels = function (successCallback, errorCallback) {
successCallback(["premium"]);
};
}
⚠️ Before you publish: turn the mock off
This is the one rule you cannot skip. The mock is a development crutch — it must never reach production. If you ship it, every user of the app will be treated as your fake premium member, regardless of what they've actually paid for.
Two safe habits:
- Keep everything behind the single
PREVIEW_TESTINGflag and set it tofalsebefore publishing. - Better yet, delete the mock block entirely once you've finished testing.
When PREVIEW_TESTING is false (or the block is gone), gb.user.getCurrent falls back to GoodBarber's real implementation, and your Custom Code works against actual logged-in members.
Ready to try it? Open the Custom Code section in your GoodBarber back office, paste the mock block at the top of your JavaScript, and set the access_levels for the case you want to test. When everything behaves, flip PREVIEW_TESTING to false (or delete the block) and publish. For the full reference, see the App API documentation.
And if you'd rather not write the extension by hand, that's where the AI Extension Builder comes in: describe the section you want in plain language and it generates the extension, plugs it into GoodBarber's own APIs, and renders it live in your app. It builds on the same App API — so the technique above is right there whenever you want to preview how your extension behaves for a logged-in member.
Further reading
gb.user.getCurrent— retrieve the current logged-in user.GBUser— the user model and how its attributes change perapi_version.gb.membership.getAccessLevels— read access levels directly (available only with the Memberships add-on).- GoodBarber for developers: more freedom and power-user tools — what you can build beyond the no-code editor.
Recap
- In the back-office preview, there is no real login.
- For Authentication and eCommerce apps, GoodBarber injects a fake user automatically, so testing as a logged-in user just works.
- For the Membership extension, no fake user is provided —
getCurrent()hits the error callback. - To test fast in the preview, temporarily override
gb.user.getCurrent(andgb.membership.getAccessLevelsif you use it) to return a fake member with theaccess_levelsyou want to test. - For a real, end-to-end check, run your app inside the MyGoodBarber app.
- Always remove the mock before publishing.
FAQ
Why does gb.user.getCurrent() return an error in the preview for my Membership app?
Because the back-office preview has no login mechanism, and for Membership apps (api_version: 3) GoodBarber does not inject a fake user. With nobody logged in, the method calls your error callback with "There's no user logged in the app." — this is expected behavior, not a bug.
Why does the same code work in the preview for an Authentication or eCommerce app?
For Authentication (api_version: 1) and eCommerce (api_version: 2) apps, GoodBarber automatically injects a fake user (or fake customer) in the preview, so your success callback fires without any setup.
How do I test a logged-in member without publishing my app?
Either run your app inside the MyGoodBarber app (iOS/Android) to test under real conditions, or temporarily override gb.user.getCurrent in your Custom Code to return a fake member with the access_levels you want to test.
What is access_levels in the GBUser object?
It's an array of the access levels a Membership user currently holds (for example ["premium"]). Your Custom Code typically branches on it to decide what content to show. An empty array ([]) means a logged-in user with no active subscription.
Does gb.user.getCurrent() return a Promise?
No. It's callback-based: you pass a success callback and an error callback. It does not return a value, so you can't await it.
What happens if I forget to remove the mock before publishing?
Every user of your app will be treated as the fake member you hard-coded — they'd all get, say, premium access regardless of what they actually paid for. Always set PREVIEW_TESTING to false or delete the mock block before you publish.
