Jump to content

Theme customization: how to add support for paid video channels


Tech Support

Recommended Posts

KVS supports ability to sell subscriptions to individual profiles and channels. These subscriptions work using the internal token system and have the following features:

  • A subscription can be for unlimited period, or for the given period of days. It is possible to specify only 1 period, which will affect all subscriptions of the same type (e.g. you can configure 1 period for subscription on profiles, and another period for subscription on channels).
  • A subscription should be paid in tokens, so that users first need to purchase tokens using one of the supported and configured payment processor.
  • Subscription means premium access to all videos uploaded by the given profiles or into the given channel.
  • Subscription price can be set in admin panel for each profile / channel separately, or in site frontend in profile / channel editor (this field should be added into theme layout, not exist by default). So ultimately each member can have multiple paid channels with different prices, as well as separate price for the whole member's profile.
  • If subscription is durable, at the end of subscription period KVS will try to deduct the needed amount of tokens from the user's account (e.g. rebill the subscription). If there will be no tokens on user's balance within 24 hours, the subscription will not be renewed. Unfortunately at the time of writing (5.5.1 KVS version) there is no support for sending emails, alerts to users at the moment with regard to this issue. Will be added in future.
  • It is possible to configure that users who sell subscriptions to their profiles or channels will get some % of revenue in tokens paid by buyers.

For simplicity this guide will consider the case when you activate only 1 type of subscription at a time: either channels or profiles. If you want to consider having both profile and channel subscriptions at a time, you will need more robust template coding to render video purchase forms correctly, because the same video can be accessed via channel subscription, or via profile subscription and thus 2 purchase options should be displayed. However the provided examples give the full code needed to create both cases and only minor IF / ELSE adjustments are needed.

If you want to start using this feature you should first consider configuring a payment processor in Memberzone -> Billings. You need to choose a processor that supports tokens: SegPay, Paypal and Verotel at the moment + CoinPayments added in the new version already. For configuring them please create support ticket after you have your account approved at billing's side.

 

Activating paid subscriptions in admin panel

The very few and easy settings are located in Settings -> Memberzone Settings under Paid subscriptions section. You need to activate paid subscriptions for profiles and/or channels, set their default price as 0 and subscription duration as needed (leave empty for unlimited duration).

In the next section you can also activate earning tokens from selling profiles and/or channels and specify your commission. Here is how the settings will look like for 30-day channel subscriptions with users earning 90% of all paid tokens (10% is your service fee):

enable_channels.thumb.png.dd7b8a96492fdb39bc70203d5674ea85.png

 

Adding fields for users to specify subscription price

There could be 2 places where you may need to add this field based on whether you plan profile and/or channel subscriptions.

For channels:

Go to Website UI -> Language files -> default and add the following lines:

edit_channel.field_tokens_required = Price in tokens
edit_channel.field_tokens_required_hint = specify price for paid channels

Then go to Website UI -> Global blocks -> Edit Channel Form and add the following code into the desired place to render token price field:

<div class="row">
	<label for="edit_channel_tokens_required" class="field-label">{{$lang.edit_channel.field_tokens_required}}</label>
	<input type="number" name="tokens_required" id="edit_channel_tokens_required" class="textfield" value="{{if $smarty.post.tokens_required>0}}{{$smarty.post.tokens_required}}{{/if}}" min="0" placeholder="{{$lang.edit_channel.field_tokens_required_hint}}" {{if $is_locked=='true'}}readonly{{/if}}/>
	<div class="field-error down"></div>
</div>

 

For profiles:

Go to Website UI -> Language files -> default and add the following lines:

edit_profile.field_tokens_required = Price in tokens
edit_profile.field_tokens_required_hint = specify price for paid profiles

Then go to Website UI -> Theme settings and under Profile options field find the active link (in some themes there could be several profile editing forms and only one of them is active). Then in the profile edit block settings add the following code into template where you want it to be displayed:

<div class="row">
	<label for="edit_profile_tokens_required" class="field-label">{{$lang.edit_profile.field_tokens_required}}</label>
	<input type="number" name="tokens_required" id="edit_profile_tokens_required" class="textfield" value="{{if $smarty.post.tokens_required>0}}{{$smarty.post.tokens_required}}{{/if}}" min="0" placeholder="{{$lang.edit_profile.field_tokens_required_hint}}" {{if $is_locked=='true'}}readonly{{/if}}/>
	<div class="field-error down"></div>
</div>

 

Closing access to videos in paid channels / from paid profiles

Go to Website UI -> Language files -> default and add the following lines:

videos.video_player_guest.channel = This video belongs to a premium channel %CHANNEL%. Only active members can watch videos from premium channels. <br/><br/> Please <a href="%LOGIN%" data-fancybox="ajax">log in</a> or <a href="%SIGNUP%" data-fancybox="ajax">sign up</a> for free.
videos.video_player_tokens_not_enough.channel = This video belongs to a premium channel %CHANNEL%. To have access to videos in this channel you must spend <em>%TOKENS_COST%</em> tokens. <br/><br/> Your current tokens balance is <em>%TOKENS_AVAILABLE%</em> tokens. <br/> You need <em>%TOKENS_LEFT%</em> more tokens.
videos.video_player_tokens_purchase.channel = This video belongs to a premium channel %CHANNEL%. To have access to videos in this channel you must spend <em>%TOKENS_COST%</em> tokens. <br/><br/> Your current tokens balance is <em>%TOKENS_AVAILABLE%</em> tokens. <br/> Please confirm spending <em>%TOKENS_COST%</em> tokens on this video.

 

Now you need to modify video view block template in Website UI -> Pages -> View Video page -> Video View block. Locate the following line:

				{{elseif $data.can_watch==0}}

and you need to add the following block RIGHT before this line.

ATTENTION! This is the most complicated part, as you need to insert the fully copied code fragment into the specific part of Smarty template, failing to do correctly make break your video page. Please make sure you do a backup copy of original template code before you do any changes, just in case you need to restore it.

For channels:

				{{elseif $data.dvd.tokens_required>0 && $data.dvd.is_purchased==0 && $data.user_id!=$smarty.session.user_id && $data.dvd.user_id!=$smarty.session.user_id}}
					<div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%">
						<img src="{{$flashvars.preview_url}}" width="{{$player_size[0]}}" height="{{$player_size[1]}}" alt="{{$data.title}}"/>
						<span class="message">
							{{if $smarty.session.user_id<1}}
								{{$lang.videos.video_player_guest.channel|replace:"%CHANNEL%":$data.dvd.title|smarty:nodefaults|replace:"%LOGIN%":$lang.urls.login|replace:"%SIGNUP%":$lang.urls.signup}}
							{{else}}
								{{if $smarty.session.tokens_available<$data.dvd.tokens_required}}
									{{assign var="tokens_left" value=$data.dvd.tokens_required-$smarty.session.tokens_available}}
									{{$lang.videos.video_player_tokens_not_enough.channel|replace:"%CHANNEL%":$data.dvd.title|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}}
									<form>
										<input type="button" class="submit" data-fancybox="ajax" data-href="{{$lang.urls.upgrade}}" value="{{$lang.videos.video_player_tokens_btn_buy|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}">
									</form>
								{{else}}
									{{assign var="tokens_left" value=$smarty.session.tokens_available-$data.dvd.tokens_required}}
									{{$lang.videos.video_player_tokens_purchase.channel|replace:"%CHANNEL%":$data.dvd.title|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}}
									<form action="{{$data.canonical_url}}" method="post" data-form="ajax">
										<div class="generic-error hidden"></div>
										<input type="hidden" name="action" value="subscribe"/>
										<input type="hidden" name="subscribe_dvd_id" value="{{$data.dvd.dvd_id}}">
										<input type="submit" class="submit" value="{{$lang.videos.video_player_tokens_btn_spend|replace:"%TOKENS_COST%":$data.dvd.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}">
									</form>
								{{/if}}
							{{/if}}
						</span>
					</div>

 

For profiles:

				{{elseif $data.user.tokens_required>0 && $data.user.is_purchased==0 && $data.user_id!=$smarty.session.user_id}}
					<div class="no-player" style="width: 100%; height: 0; padding-bottom: {{$player_size[1]/$player_size[0]*100|replace:",":"."}}%">
						<img src="{{$flashvars.preview_url}}" width="{{$player_size[0]}}" height="{{$player_size[1]}}" alt="{{$data.title}}"/>
						<span class="message">
							{{if $smarty.session.user_id<1}}
								{{$lang.videos.video_player_guest.channel|replace:"%CHANNEL%":$data.username|smarty:nodefaults|replace:"%LOGIN%":$lang.urls.login|replace:"%SIGNUP%":$lang.urls.signup}}
							{{else}}
								{{if $smarty.session.tokens_available<$data.user.tokens_required}}
									{{assign var="tokens_left" value=$data.user.tokens_required-$smarty.session.tokens_available}}
									{{$lang.videos.video_player_tokens_not_enough.channel|replace:"%CHANNEL%":$data.username|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}}
									<form>
										<input type="button" class="submit" data-fancybox="ajax" data-href="{{$lang.urls.upgrade}}" value="{{$lang.videos.video_player_tokens_btn_buy|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}">
									</form>
								{{else}}
									{{assign var="tokens_left" value=$smarty.session.tokens_available-$data.user.tokens_required}}
									{{$lang.videos.video_player_tokens_purchase.channel|replace:"%CHANNEL%":$data.username|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left|replace:"%UPGRADE%":$lang.urls.upgrade|smarty:nodefaults}}
									<form action="{{$data.canonical_url}}" method="post" data-form="ajax">
										<div class="generic-error hidden"></div>
										<input type="hidden" name="action" value="subscribe"/>
										<input type="hidden" name="subscribe_user_id" value="{{$data.user.user_id}}">
										<input type="submit" class="submit" value="{{$lang.videos.video_player_tokens_btn_spend|replace:"%TOKENS_COST%":$data.user.tokens_required|replace:"%TOKENS_AVAILABLE%":$smarty.session.tokens_available|replace:"%TOKENS_LEFT%":$tokens_left}}">
									</form>
								{{/if}}
							{{/if}}
						</span>
					</div>

 

After adding such block, video page should turn into a locked player for paid channels / profiles, unless user purchases them:

subscription_purchase_form.png.7f5a87cf828ab0b7996bbf190db13986.png

 

Displaying subscription status for paid subscription

Note: this functionality will become possible in KVS 6.0 update.

Default theme renders list of user's subscriptions, but subscriptions can be free and paid. The default rendering doesn't separate them, and here is how to modify that.

 Go to Website UI -> Language files -> default and add the following lines:

subscriptions.list_label_paid_unlimited = (Paid, never expires)
subscriptions.list_label_paid_expired = (Paid, expired)
subscriptions.list_label_paid_active = (Paid, expires in [count]%1% days || 1: 1 day[/count])

 

Then go to Website UI -> Pages -> [Memberzone] My Profile page -> My Subscriptions block settings. Locate the following code in its template:

<a href="{{$subscribed_url}}" class="title">{{$item.title}}</a>

And change it like this:

<a href="{{$subscribed_url}}" class="title">
	{{$item.title}}
	{{if $item.purchase.purchase_id>0}}
		{{if $item.purchase.expiry_date_is_unlimited==1}}
			{{$lang.subscriptions.list_label_paid_unlimited}}
		{{elseif $item.purchase.expiry_date_hours_left<0}}
			{{$lang.subscriptions.list_label_paid_expired}}
		{{else}}
			{{assign var="days_left" value=$item.purchase.expiry_date_hours_left/24|floor}}
			{{$lang.subscriptions.list_label_paid_active|count_format:"%1%":$days_left}}
		{{/if}}
	{{/if}}
</a>

And the result will look like this:

subscription_list_display.png.3973ef80452fd3d6d1e5bbd9543feb35.png

Link to comment
Share on other sites

  • 5 months later...
  • 2 weeks later...
On 10/6/2022 at 7:35 AM, Evgen said:

I did not find how to display the number of tokens available to the user in the header of the site.

The number of tokens for the user currently logged in can be displayed like this:

{{if $smarty.session.user_id>0}}
You have {{$smarty.session.tokens_available}} tokens
{{/if}}

 

Link to comment
Share on other sites

  • 3 months later...
20 hours ago, phseven said:

I think it needs to be added in languages files , or I`m wrong ?

In template you show this text using some $lang variable:

{{$lang.some_key_here}}

Then you just need to replace "%TOKENS_COST%" with the actual value, plus in order not to have <em> as a plain text you need to disable default security formatting using |smarty:nodefaults, therefore you should have something like that (you can find similar code in video_view block template):

{{$lang.some_key_here|replace:"%TOKENS_COST%":$data.tokens_required|smarty:nodefaults}}
Link to comment
Share on other sites

4 hours ago, Tech Support said:

In template you show this text using some $lang variable:

{{$lang.some_key_here}}

Then you just need to replace "%TOKENS_COST%" with the actual value, plus in order not to have <em> as a plain text you need to disable default security formatting using |smarty:nodefaults, therefore you should have something like that (you can find similar code in video_view block template):

{{$lang.some_key_here|replace:"%TOKENS_COST%":$data.tokens_required|smarty:nodefaults}}

Thnak you it worked

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...