# Offerwall Link, Embed, and Button

> How to open the offerwall for a signed-in user, build the security hash on your server, embed it on your site, and choose which offers show.

Source: https://docs.moonetix.com/offerwall-link

## Link format

Every approved app has its own link. You find it, ready to copy, in your dashboard under Apps, your app, Integration.

```
https://wall.moonetix.com/{APP_ID}?user_id={USER_ID}&hash={HASH}
```

| Parameter | Required | Description |
| --- | --- | --- |
| `user_id` | Yes | The ID of the signed-in user in your system. 1 to 100 characters from `A-Z a-z 0-9 . _ @ : + -`. It must never change for the same user. URL-encode it. |
| `hash` | Yes, while link security is on | HMAC-SHA256 of the user ID with your link hash salt, as lowercase hex. It stops users from changing the user ID in the link to open the offerwall as someone else. |
| `sub1` to `sub5` | No | Your own tracking values, for example the traffic source or a session ID. 1 to 100 characters from `A-Z a-z 0-9 . _ ~ : @ + -`. We return them in the postback as `{sub1}` to `{sub5}`. See [Track sources with sub IDs](https://docs.moonetix.com/offerwall-link#sub-ids). |

For `user_id`, use the ID your own database gives the user, for example `1234` or a UUID. Do not use an email address or a username: those can change, which would split the user’s offers and rewards, and the ID shows up in your reports and postbacks.

Link security is on by default. You can turn it off in the Integration tab, but we do not recommend it.

## Build the hash on your server

The link hash salt is a secret. Build the hash on your server and send only the finished link to the browser. Never put the salt in JavaScript or in an app bundle.

```php
$hash = hash_hmac('sha256', $userId, $linkHashSalt);
$url  = 'https://wall.moonetix.com/' . $appId . '?user_id=' . rawurlencode($userId) . '&hash=' . $hash;
```

```javascript
const crypto = require('crypto');
const hash = crypto.createHmac('sha256', linkHashSalt).update(String(userId)).digest('hex');
const url = `https://wall.moonetix.com/${appId}?user_id=${encodeURIComponent(userId)}&hash=${hash}`;
```

```python
import hmac, hashlib
from urllib.parse import quote
hash = hmac.new(link_hash_salt.encode(), str(user_id).encode(), hashlib.sha256).hexdigest()
url = f"https://wall.moonetix.com/{app_id}?user_id={quote(str(user_id))}&hash={hash}"
```

In Integration status on the Integration tab, **Check a link** has a **Test a link** tool: type a user ID and it shows the exact link your server should build.

## Track sources with sub IDs

Add up to five of your own values to the link to see where your earnings come from, for example which page, campaign, or placement opened the offerwall:

```
https://wall.moonetix.com/{APP_ID}?user_id={USER_ID}&hash={HASH}&sub1=homepage&sub2=summer_promo
```

- We save the values when the user starts an offer and send them back in every postback of that transaction as `{sub1}` to `{sub5}`. A sub ID you did not send is empty.
- The same values are in the [Reporting API](https://docs.moonetix.com/reporting-api), which can also group your statistics by `sub1` to `sub5`.
- A value with other characters or more than 100 characters is ignored. URL-encode the values.
- Sub IDs are not part of the hash, so users can change them. Use them for tracking only, and always credit users by `{user_id}`.

## Embed it on your site

Put the offerwall on one of your pages with an iframe. It is as tall as the screen and scrolls on its own, so there is no second scroll bar.

```html
<iframe title="Offerwall" src="https://wall.moonetix.com/{APP_ID}?user_id={USER_ID}&amp;hash={HASH}"
  style="border:0;width:100%;height:100vh"></iframe>
```

- The Integration tab of your app has this code with your link already in it.
- Change `100vh` if you want another height, for example `calc(100vh - 64px)` under a fixed header.
- Keep the `style`: without it, browsers show the frame as a small 300 by 150 pixel box.

### Floating button

Add one line to any page to show a button in the corner. It opens the offerwall in a pop-up over your site, so users do not leave the page they are on.

```html
<script src="https://wall.moonetix.com/embed.js" async
  data-button-url="https://wall.moonetix.com/{APP_ID}?user_id={USER_ID}&amp;hash={HASH}"
  data-button-text="Earn rewards"
  data-button-color="#004ABB"
  data-button-position="right"></script>
```

| Attribute | Required | Description |
| --- | --- | --- |
| `data-button-url` | Yes | The signed offerwall link of the user. It must start with `https://wall.moonetix.com/`, or no button is shown. |
| `data-button-text` | No | The button text, up to 40 characters. Default: Earn rewards. |
| `data-button-color` | No | The button color as a six-digit hex code, for example `#004ABB`. The text turns dark or light by itself so it stays readable. |
| `data-button-position` | No | `right` or `left`. Default: right. |

Users close the pop-up with the close button, the Escape key, or a click outside it.

### Open it from your own button or link

Already have a menu item or a button for rewards? Add `data-moonetix-open` to it and load the script once on the page:

```html
<a href="https://wall.moonetix.com/{APP_ID}?user_id={USER_ID}&amp;hash={HASH}" data-moonetix-open>Earn rewards</a>
<script src="https://wall.moonetix.com/embed.js" async></script>
```

A click opens the pop-up instead of a new page. If the script does not load, the link still opens the offerwall as a normal page. From your own JavaScript, call `Moonetix.open(link)` with the signed link.

### Where it works

- For safety, the offerwall only loads inside frames and pop-ups on the website you registered for the app and its subdomains, and only on https pages. Opening the link directly in a tab, a new window, or a mobile WebView works everywhere.
- The script only opens links that start with `https://wall.moonetix.com/`, and never runs code from the page or the button text.
- Build the signed link on your server as shown above. The script never needs your salt or keys.

## Choose which offers your users see

The Offers page of your dashboard lists every offer your app can show, with its countries, status, your payout, the conversion rate, and the EPC. Click Hide on an offer to remove it, and Show to bring it back. A hidden offer is left out of your offerwall, the embedded offerwall, the floating button, direct links, and the [Offers API](https://docs.moonetix.com/offers-api) of that app. The search, the filters, and the sort order only change the list on the page, not what your users see.

Changes apply right away, to users who already have the offerwall open as soon as the list reloads. Every hidden offer means fewer offers for your users, so hide only what really does not fit.

To send users to one offer, click its name on the Offers page and copy the offer link from its details. Fill in `{USER_ID}` and `{HASH}` exactly as in your offerwall link. Rewards and postbacks are the same as on your offerwall.

```
https://wall.moonetix.com/{APP_ID}/offer/{OFFER_ID}?user_id={USER_ID}&hash={HASH}
```

## Mobile apps

Open the link in a WebView or in the system browser. Build the link on your backend and pass it to the app, so the salt stays on your server. For a native screen instead, use a mobile SDK: [Android](https://docs.moonetix.com/android-sdk), [iOS](https://docs.moonetix.com/ios-sdk), [Flutter](https://docs.moonetix.com/flutter-sdk), [React Native](https://docs.moonetix.com/react-native-sdk), or [Unity](https://docs.moonetix.com/unity-sdk).

## What your users see

- **Menu:** Earn and My offers, at the top. Earn shows the offers available for their country and device, with top offers first, search, categories, and sorting.
- **My offers:** one list of every offer they started, the most recent first, with its rewards, goals, and status: In progress, Confirming, Completed, or Expired, plus a Reversed mark when a reward was taken back. If a reward is missing, they tap Report on the offer.
- A note that offers come from third-party advertisers, and links to our Terms of Service and Privacy Policy.

## Error pages

| Page | HTTP status | Reason |
| --- | --- | --- |
| Link not valid | 403 | The hash is missing or does not match the user ID. |
| Missing user ID | 400 | The `user_id` parameter is missing or has characters we do not accept. |
| Offerwall paused | 404 | Our team paused the app. Check your notifications. |
| Offerwall not available | 404 | The app does not exist or is not available, for example because it was rejected or its account is not approved or not active. |
| Access blocked | 403 | We blocked the user’s IP address. |
| VPN detected, Proxy detected, Tor detected | 403 | The user is on a VPN, a proxy, or Tor. Offers cannot track users through them. See [Test from a normal connection](https://docs.moonetix.com/testing#vpn). |
| Network not supported | 403 | The user connects from a server or data center network, for example a cloud server. |
| Not available | 403 | Our team blocked this user on your app, for example after fraud. The user sees that offers are not available for their account. |
| Session not valid | 404 | A mobile SDK opened the offerwall with a token we do not know. The SDK reports `INVALID_TOKEN`. |
| Session ended | 410 | The SDK token was already used or is older than 10 minutes. The SDK reports `TOKEN_EXPIRED_OR_USED`. |
| Too many requests | 429 | Too many requests from the same network or for the same user in a short time. The user can try again after a minute. |
