Link custom user field to external website

Hi @techAPJ, I am new to discourse customizing but attempting your tutorial at our forum.

To begin, I’ve used the same custom field name as yours (User Profile) and followed rest of the tutorial. However, I am not seeing any links being added to user cards or public profiles.

We are using SSO to register users to the forum but that should not affect getting a link with user ID right? Could you please check the implementation here. Thanks in advance for any suggestions as to what I am doing wrong.

Hi Mike,

I just updated the guide to work with latest Discourse version, try going through the steps again with updated code and everything should be good.

4 Likes

Thanks, @techAPJ.
I followed the tutorial 3 times to make sure I did not miss any instructions but I still can’t get the external profile URL to show up in user profile page or user card. I kept your field name as is to minimize alterations to the code. So the only change I did was to replace ‘myawesomewebsite’.

Do you know what could be the issue?

I am seeing this warning in console on your site:

Plugin API v0.6 is not supported

You need to be on latest Discourse version.

@techAPJ Updated Discourse and all components now. And I no longer see console errors. However, the links are still not visible.

I also noticed the guide haven’t changed from what I did last time (28d ago), were your changes done via the discourse code itself? Thanks again for your help so far.

The issue was happening because this guide is not for linking a username to the main site.
If you are looking for such functionality please refer to this new guide

3 Likes

This is really nifty, I’ve added two fields users can fill, Twitch and Steam. Eventually might even add more.
I’m now trying to have the link displayed as fa icon. This is working, but this way it will display every icon on a new line, so I’ve been trying to combine this, but I’m having issues with it.

<script type="text/discourse-plugin" version="0.6">
    const User = api.container.lookupFactory('model:user');

    api.registerConnectorClass('user-profile-primary', 'steam-link', {
      setupComponent(args, component) {
        component.set('steamLink', args.model.get('steamLink'));
      }
    });

    api.registerConnectorClass('user-card-metadata', 'steam-link', {
      setupComponent(args, component) {
        component.set('steamLink', args.user.get('steamLink'));
      }
    });
    
    api.registerConnectorClass('user-profile-primary', 'twitch-link', {
      setupComponent(args, component) {
        component.set('twitchLink', args.model.get('twitchLink'));
      }
    });

    api.registerConnectorClass('user-card-metadata', 'twitch-link', {
      setupComponent(args, component) {
        component.set('twitchLink', args.user.get('twitchLink'));
      }
    });

This part isn’t that hard, the question is, how do I combine the data, and how do I configure an and/or statement so it also works if a user only added one of the two fields. And, if I add more fields in the future, how I would add them as well.

I figured, if this all happens before I build the HTML, it will be easier to add all icons on the card and profile on one line. :slight_smile:

Anyone with some tips/insights? Right now every field goes through something like this:

<script type='text/x-handlebars' data-template-name='/connectors/user-profile-primary/twitch-link'>
  {{#if twitchLink}}
    <div class="public-user-fields">
      <div class="public-user-field">
        <span class="user-field-value">{{{twitchLink.link}}}</span>
      </div>
    </div>
  {{/if}}
</script>

<script type='text/x-handlebars' data-template-name='/connectors/user-card-metadata/twitch-link'>
  {{#if twitchLink}}
    <h3 class="user-card-public-field">
      <span class="user-field-value">{{{twitchLink.link}}}</span>
    </h3>
  {{/if}}
</script>

How do I tell the {{#if twitchLink}} that it also needs to check for Steam (and maybe Twitter, Facebook, etc. etc.), and display all the icons on one line?

This is the way it is now, so it kind of works, but I would like to have the icons on one line. Because they are generated separately, there are emberxxx classes created, with div’s/span’s with the same name…

What would be the best way to have these icons “generated” on one line?

1 Like

It sounds like you’re doing something like this currently:

<script type='text/x-handlebars'>
  {{#if twitchLink}}
     [...]
  {{/if}}
</script>

<script type='text/x-handlebars'>
  {{#if steamLink}}
    [...]
  {{/if}}
</script>

If instead you do this:

<script type='text/x-handlebars'>
  {{#if twitchLink}}
     [...]
  {{/if}}
  {{#if steamLink}}
    [...]
  {{/if}}
</script>

You can then simply set the style attribute on the outermost div or h3 to display: inline-block;, so, something like this:

{{#if twitchLink}}
  <div class="public-user-fields" style="display: inline-block;">
     [...]

(Or just use elements which are naturally inline).

If you’re looking for more inspiration, this gist should do what you want:

Change the object on line 4 of head.html to change the row of icons, and on line 50 to change the icon & text combo which appears next to the location/site.

11 Likes

Awesome! Gonna check that out later on my desktop. I’ve managed to get the icons on one line through some styling, that screenshot looks a lot better though. Thanks! I’ll post back later! :heart:

1 Like

This looks great, thanks for sharing! But do I understand correctly that that entire code is loaded with every page and that that code will perform multiple api calls every time? (I’m sorry if this is a very dumb question. I don’t know any javascript, just guessing.)

The code piggybacks on the existing code to load the user cards/profiles, so no additional API calls are done, just the usual one to /u/<username>.json. But yes, the entire code is loaded on every ‘real’ page load (i.e. when you hit Discourse from an external site or from typing in a url, or refresh a page), much the same way all the rest of Discourse’s client side code is loaded on every real page load.

3 Likes

Is there an easy way to implement this? I would like to use external_id in my link, but I’m still not clear on how I would go about doing that.

Thanks!

This needs to be done on SSO side, so you will need to look into how your SSO is set-up.

1 Like

I’m just using the WP Discourse plugin.

When I visit the user profile as admin (/admin/users/2/[username]), I do see the External ID under the Single Sign On section at the bottom.

Does that move me any further ahead in the process? Is it just a matter of properly modifying OP’s code?

@Simon_Cossar, is there a good way to do this in the WP Discourse plugin?

Yes, there is. What data do you want to add to the field?

1 Like

Just the External ID to a custom field.

Aside from that, it would be cool if there was an easy way to do it for other fields as well. (ie location or any custom fields on the WP side).

It’s not as easy as I thought. I might not be doing this correctly.

It’s possible to set the value of a UserCustomField through the SSO parameters sent from WordPress by hooking into the wpdc_sso_params filter. If you create a ‘wordpress id’ User Field on Discourse, you can then create new Discourse UserCustomField record by doing something like this:

add_filter( 'wpdc_sso_params', 'my_namespace_custom_fields', 10, 2 );
function my_namespace_custom_fields( $sso_params, $user ) {
    $sso_params['custom.wordpress_id'] = $user->ID;

	return $sso_params;
}

The problem I’m having is that I can’t figure out how to access the value of that record on the front-end of Discourse.

3 Likes

Thanks Simon! Yeah I just poked around as well and couldn’t find the field name anymore. How did you find it through the console?