Added FirstPromoter integration

no issue
depends on https://github.com/TryGhost/Ghost/pull/12540

FirstPromoter allows sites to build their own referral programs.
Portal reads FirstPromoter settings from site data and uses them to setup FirstPromoter script to track member referrals
This commit is contained in:
Rish 2021-01-11 23:38:05 +05:30
parent 72c8cad3f5
commit a085063a42
4 changed files with 57 additions and 6 deletions

View File

@ -9,7 +9,7 @@ import * as Fixtures from './utils/fixtures';
import ActionHandler from './actions';
import './App.css';
import NotificationParser from './utils/notifications';
import {capitalize, createPopupNotification, hasPlan, isComplimentaryMember, removePortalLinkFromUrl} from './utils/helpers';
import {capitalize, createPopupNotification, getFirstpromoterId, getSiteDomain, hasPlan, isComplimentaryMember, removePortalLinkFromUrl} from './utils/helpers';
const React = require('react');
const DEV_MODE_DATA = {
@ -146,7 +146,6 @@ export default class App extends React.Component {
const {site: linkSiteData, ...restLinkData} = this.fetchLinkData();
const {site: previewSiteData, ...restPreviewData} = this.fetchPreviewData();
const {site: notificationSiteData, ...restNotificationData} = this.fetchNotificationData();
let page = '';
return {
@ -270,6 +269,7 @@ export default class App extends React.Component {
const {siteUrl} = this.props;
this.GhostApi = setupGhostApi({siteUrl});
const {site, member} = await this.GhostApi.init();
this.setupFirstPromoter({site, member});
return {site, member};
} catch (e) {
if (hasMode(['dev', 'test'])) {
@ -279,6 +279,42 @@ export default class App extends React.Component {
}
}
setupFirstPromoter({site, member}) {
const firstPromoterId = getFirstpromoterId({site});
const siteDomain = getSiteDomain({site});
if (firstPromoterId && siteDomain) {
const t = document.createElement('script');
t.type = 'text/javascript';
t.async = !0;
t.src = 'https://cdn.firstpromoter.com/fprom.js';
t.onload = t.onreadystatechange = function () {
let _t = this.readyState;
if (!_t || 'complete' === _t || 'loaded' === _t) {
try {
window.$FPROM.init(firstPromoterId, siteDomain);
if (member) {
const email = member.email;
const uid = member.uuid;
if (window.$FPROM) {
window.$FPROM.trackSignup({email: email, uid: uid});
} else {
const _fprom = window._fprom || [];
window._fprom = _fprom;
_fprom.push(['event', 'signup']);
_fprom.push(['email', email]);
_fprom.push(['uid', uid]);
}
}
} catch (err) {
// Log FP tracking failure
}
}
};
const e = document.getElementsByTagName('script')[0];
e.parentNode.insertBefore(t, e);
}
}
/** Handle actions from across App and update state */
async onAction(action, data) {
clearTimeout(this.timeoutId);
@ -337,7 +373,7 @@ export default class App extends React.Component {
/**Fetch Stripe param from site url after redirect from Stripe page*/
getStripeUrlParam() {
const url = new URL(window.location);
const url = new URL(window.location.href);
return (url.searchParams.get('stripe') || url.searchParams.get('portal-stripe'));
}

View File

@ -134,7 +134,7 @@ function InputField({
onBlur={e => onBlur(e, name)}
disabled={disabled}
tabIndex={tabindex}
maxlength={maxlength}
maxLength={maxlength}
autoComplete={autocomplete}
autoCorrect={autocorrect}
autoCapitalize={autocapitalize}

View File

@ -13,6 +13,9 @@ function addRootDiv() {
}
function getSiteUrl() {
/**
* @type {HTMLElement}
*/
const scriptTag = document.querySelector('script[data-ghost]');
if (scriptTag) {
return scriptTag.dataset.ghost;
@ -21,7 +24,7 @@ function getSiteUrl() {
}
function handleTokenUrl() {
const url = new URL(window.location);
const url = new URL(window.location.href);
if (url.searchParams.get('token')) {
url.searchParams.delete('token');
window.history.replaceState({}, document.title, url.href);

View File

@ -163,6 +163,10 @@ export const getMemberEmail = ({member}) => {
return member.email;
};
export const getFirstpromoterId = ({site}) => {
return (site && site.firstpromoter_id);
};
export const getMemberName = ({member}) => {
if (!member) {
return '';
@ -175,7 +179,15 @@ export const getSupportAddress = ({site}) => {
return supportAddress || '';
};
export const createPopupNotification = ({type, status, autoHide, duration, closeable, state, message, meta}) => {
export const getSiteDomain = ({site}) => {
try {
return (new URL(site.url)).origin;
} catch (e) {
return site.url.replace(/^http(s?):\/\//, '').replace(/\/$/, '');
}
};
export const createPopupNotification = ({type, status, autoHide, duration, closeable, state, message, meta = {}}) => {
let count = 0;
if (state && state.popupNotification) {
count = (state.popupNotification.count || 0) + 1;