Skip to content

v4.5.0 - Touchpoints 2.0: Server-Composed Touchpoint Serve API

Choose a tag to compare

@AdnanKhurshid26 AdnanKhurshid26 released this 18 Sep 07:45
· 1 commit to main since this release
8ed17a8

PlaySuper Unity SDK v4.5.0

Touchpoints 2.0. A new, server-composed touchpoint API. Your game asks for the screen it is about to show, and PlaySuper answers with the frame artwork the studio chose in the console and one concrete offer already composed into it, priced for that player with the coin maths done. The game draws two images and opens a URL. Nothing to walk, nothing to interpret.

What's New

🎯 TouchpointV2Manager.Serve — one call per screen

using PlaySuperUnity;

var tp = await TouchpointV2Manager.Serve(TouchpointV2Manager.Screens.Home);

if (tp == null)
{
    // The request itself failed (SDK not initialised, network, non-2xx). Already logged.
    return;
}

if (!tp.HasTouchpoint)
{
    // Nothing configured for this screen, or no catalogue item available right now.
    // This is a normal state, not an error — draw nothing.
    return;
}

// Frame + offer art
frameImage.LoadFromUrl(tp.FrameImageUrl);          // tp.asset.imageUrl
offerImage.LoadFromUrl(tp.OfferImageUrl);          // tp.item.imageUrl

// Copy
titleText.text  = tp.item.title;
ctaButton.text  = tp.item.cta.label;               // e.g. "Claim now"

// Tap → store, landing on this exact offer with attribution intact
ctaButton.onClick.AddListener(() => TouchpointV2Manager.OpenCta(tp));

Serve(screen, type, utmSource, utmMedium, utmCampaign) hits GET /v2/touchpoints/serve and returns a TouchpointV2Response. Only screen is required.

  • screen — use TouchpointV2Manager.Screens.Home. home is the only live screen in this release; other slugs are rejected with a 400 that names the valid ones.
  • type — optional filter from TouchpointV2Manager.ItemType (Product, Coupon, GiftCard). Only needed when the studio has placed more than one kind of offer on the same screen; the API rejects an ambiguous call rather than picking for you.
  • utmSource / utmMedium / utmCampaign — optional. Appended server-side to the CTA URL.

📦 A response you can render directly

Field What it is
asset The frame. imageUrl, orientation (PORTRAIT / LANDSCAPE), source (PRESET / UPLOAD), optional width / height.
item The offer inside the frame. type (PRODUCT / COUPON / GIFT_CARD), title, subtitle, brandName, imageUrl, pricing, coins, offerText, cta.
item.pricing currency, mrp, price, priceAfterCoins, discountPct. All computed server-side for this player and this game's coin. discountPct is the pre-coin MRP → price badge; the coin saving is reported separately.
item.coins coinsRequired, coinDiscount, plus coinId / coinName / coinImageUrl. Null when this game's coin cannot be spent on the item or the saving rounds to nothing.
item.offerText Pre-formatted coupon line, e.g. "Flat 40% off up to ₹200". Display as given.
item.cta label and an absolute store url with attribution already appended.
placementId, servedAt The console placement this came from and when the server composed it.

Convenience properties on the response: HasTouchpoint, FrameImageUrl, OfferImageUrl, IsPortrait.

🔗 TouchpointV2Manager.OpenCta — open the store at the offer

Hands the CTA's own URL to OpenStore, so the player lands on the item they tapped rather than the storefront. The URL already carries the campaign attribution the server appended, and OpenStore reads it back off. Build the URL yourself and that attribution is silently lost for every touchpoint you open.

👤 Player-aware pricing

When a player is signed in, the SDK sends their token with the request and the offer comes back priced for them. An anonymous call still returns a touchpoint, just without player-specific pricing. Either way, no arithmetic in the game.


Behaviour to Know

  • null means the call failed. HasTouchpoint == false does not. A screen the studio hasn't configured, or one with no catalogue item currently available, is a 200 with empty asset and item. Check HasTouchpoint before drawing; don't null-test the response for that.
  • asset and item arrive together or not at all. A frame with an empty centre is never served, so HasTouchpoint is a single check.
  • Unknown screen → the 400 body is logged, not just the status code. It lists the screens that would have worked.
  • Query parameters are escaped, so a UTM value carrying & or a space cannot truncate the request.
  • Console setup is required. A touchpoint is only served once the studio has an active placement for that screen in the PlaySuper console. Until then Serve succeeds and HasTouchpoint is false.

Upgrade Notes

  • Purely additive. No breaking API changes. Drop-in replacement for v4.4.x.
  • No code changes required in your game unless you adopt Touchpoints 2.0.
  • The v1 TouchpointManager is unchanged and still available. Touchpoints 2.0 is the recommended path for new integrations.
  • No manifest, Gradle, Info.plist or permissions changes.
  • No store-side changes required.
  • Android and iOS behaviour is otherwise unchanged.
  • The PlaySuper docs and console integration step gate Touchpoints 2.0 on SDK 4.5.0 or later. Confirm package.json reports 4.5.0 after updating.

Under the Hood (for developers)

  • New file: Runtime/TouchpointV2.cs. Everything in this release lives here: the TouchpointV2* response types (mirroring the server's ServeTouchpointResponseDto field for field), the internal API wrapper, and the static TouchpointV2Manager.
  • Endpoint: GET {baseUrl}/v2/touchpoints/serve?screen=…[&type=…][&utm_source=…][&utm_medium=…][&utm_campaign=…] with Accept: application/json, x-api-key, and Authorization: Bearer when a player token is present.
  • Transport: UnityWebRequest awaited via Task.Yield(); response parsed with Newtonsoft.Json. Nullable fields use NullValueHandling.Ignore.
  • Naming: the screen constants class is Screens, not Screen, to avoid shadowing UnityEngine.Screen in any file with using UnityEngine.
  • Version: package.json bumped 4.4.0 → 4.5.0.