Custom URLs

How to build dynamic URLs

Custom URLs allow you to pull data from your server or OneSignal and put it into URLs that can be used to navigate users to a specific pages, add tracking for better analytics, and display personalized content. This guide will explain the data that can be used, how to setup the URLs, and provide some example use cases.

Data Sources

Custom URLs can include data pulled from sources outlined in Message Personalization such as:

  • Properties: Data collected by OneSignal that lives on the User or Subscription (e.g external_id, email)
  • Data Tags: Custom data you send to OneSignal that live on the User.
  • Custom Data API: Data you send through the OneSignal API, usually generated on your server.

URL Setup

Using Liquid Syntax, set the custom property within your URL. Here are some examples based on the data sources.

Property URL Setup

A common example is to include the External ID or email address within the URL, but you can use any properties captured by OneSignal.


If for some reason a property is not set, you can include a default.

  •{{subscription.external_id | default: 'unknown'}}

If the user's External ID is not set, they will navigate to URL:

Tags URL Setup

Just like with property substitution, you can include Data Tags set on users for more custom personalizations. The tag values will replace the key referenced and can be accessed via the User property {{user.tags.[key]}} or the tag name directly {{ [key] }}.

For example, if you tag a user with user_name : OneSignal4Eva they [key] is user_name and you want to access an image resource stored for this user. The URL would could look like these:


Both would provide the same URL:

Like all liquid syntax, this works with the default property as well.

Custom Data URL Setup

You can pass in and access data stored on your sever within messages. This requires:

Setup the template to include the variable names within your liquid syntax. Then in your API requests, include the template_id and set custom_data from your server.

Your template's Liquid Syntax will use {{ message.custom_data.[key] }} and your custom_data property is an object containing those keys.

For example, if you send a confirmation_code unique for a specific email address that is generated on your server. You would create an email template with a button or link like:


Once your server generates the confirmation code, you would pass that into the API request:

  "app_id": "5eb5a37e-b458-11e3-ac11-000c2940e62c",
  "include_aliases": {"external_id": ["userA"]},
  "template_id": "8458af75-4da2-4ecf-afb5-f242a8926cc3",
  "custom_data": {"confirmation_code": confirmation_code}

Example Use Cases

Launch URL & Deep Linking

If using custom links in your messages or Launch URLs for push notifications, these require a protocol in the format identifier:// like https:// or app_name://. Its common to need personalization in these URIs such as properties like user.external_id or custom Data Tags.

User ID Substitution Example

If you want to send the user to their specific profile page and leverage External ID alias. You can use the URL:{{subscription.external_id}}

Custom Page Example

If you want to send the user to a specific page, like an item they were interested in purchasing. You would tag them with something like: "item_of_interest" : "itm5762" and the URL would be:{{item_of_interest}}

See URLs, Links and Deep Links for more details.

Custom Images Substitution

You can include image URLs in custom_data or Data Tags. Its possible to set full image URLs and, if your server hosts images with the same format, reference just the image identifier. For tagging, it is recommended to only tag the variable data. For example, you want include the image of an item a user added to their cart.

You could tag the user with the full image resource url like: image_url:

Then substitute this into your messages with {{ image_url }}

But if all your images are categorized by some product ID, then you can simply tag the user with product_id : item-345 and your URLs will look like this:


For custom_data, you can pass image_url into the API like this: "custom_data": { "image_url": "" }

Then substitute into your message with {{ message.custom_data.image_url }}.

One-Time Passcodes (OTP)

See Transactional Messages for details.