FEATURE: house ads can be configured to alternate with other ads
Use the new "house ads frequency" site setting to configure how often house ads should show, as a percentage. This only applies in ad placements where other ad networks are configured to appear.
This commit is contained in:
parent
cdc14398ba
commit
4bd2035866
|
@ -24,7 +24,10 @@ module ::AdPlugin
|
||||||
ad_names = settings.values.map { |v| v.split('|') }.flatten.uniq
|
ad_names = settings.values.map { |v| v.split('|') }.flatten.uniq
|
||||||
ads = AdPlugin::HouseAd.all.select { |ad| ad_names.include?(ad.name) }
|
ads = AdPlugin::HouseAd.all.select { |ad| ad_names.include?(ad.name) }
|
||||||
{
|
{
|
||||||
settings: settings.merge(after_nth_post: SiteSetting.house_ads_after_nth_post),
|
settings: settings.merge(
|
||||||
|
after_nth_post: SiteSetting.house_ads_after_nth_post,
|
||||||
|
house_ads_frequency: SiteSetting.house_ads_frequency
|
||||||
|
),
|
||||||
creatives: ads.inject({}) { |h, ad| h[ad.name] = ad.html; h }
|
creatives: ads.inject({}) { |h, ad| h[ad.name] = ad.html; h }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component";
|
||||||
|
import {
|
||||||
|
default as computed,
|
||||||
|
observes
|
||||||
|
} from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
const adConfig = Ember.Object.create({
|
const adConfig = Ember.Object.create({
|
||||||
"google-adsense": {
|
"google-adsense": {
|
||||||
settingPrefix: "adsense" // settings follow naming convention
|
settingPrefix: "adsense", // settings follow naming convention
|
||||||
|
enabledSetting: "adsense_publisher_code",
|
||||||
|
nthPost: "adsense_nth_post_code"
|
||||||
},
|
},
|
||||||
"google-dfp-ad": {
|
"google-dfp-ad": {
|
||||||
settingPrefix: "dfp" // settings follow naming convention
|
settingPrefix: "dfp", // settings follow naming convention
|
||||||
|
enabledSetting: "dfp_publisher_id",
|
||||||
|
nthPost: "dfp_nth_post_code"
|
||||||
},
|
},
|
||||||
"amazon-product-links": {
|
"amazon-product-links": {
|
||||||
settingPrefix: "amazon",
|
settingPrefix: "amazon",
|
||||||
|
enabledSetting: false,
|
||||||
|
nthPost: "amazon_nth_post_code",
|
||||||
desktop: {
|
desktop: {
|
||||||
"topic-list-top": "amazon_topic_list_top_src_code",
|
"topic-list-top": "amazon_topic_list_top_src_code",
|
||||||
"post-bottom": "amazon_post_bottom_src_code",
|
"post-bottom": "amazon_post_bottom_src_code",
|
||||||
|
@ -25,6 +35,8 @@ const adConfig = Ember.Object.create({
|
||||||
},
|
},
|
||||||
"codefund-ad": {
|
"codefund-ad": {
|
||||||
settingPrefix: "codefund",
|
settingPrefix: "codefund",
|
||||||
|
enabledSetting: "codefund_property_id",
|
||||||
|
nthPost: "codefund_nth_post",
|
||||||
desktop: {
|
desktop: {
|
||||||
"topic-list-top": "codefund_top_of_topic_list_enabled",
|
"topic-list-top": "codefund_top_of_topic_list_enabled",
|
||||||
"post-bottom": "codefund_below_post_enabled",
|
"post-bottom": "codefund_below_post_enabled",
|
||||||
|
@ -34,6 +46,7 @@ const adConfig = Ember.Object.create({
|
||||||
},
|
},
|
||||||
"carbonads-ad": {
|
"carbonads-ad": {
|
||||||
settingPrefix: "carbonads",
|
settingPrefix: "carbonads",
|
||||||
|
enabledSetting: "carbonads_serve_id",
|
||||||
desktop: {
|
desktop: {
|
||||||
"topic-list-top": "carbonads_topic_list_top_enabled",
|
"topic-list-top": "carbonads_topic_list_top_enabled",
|
||||||
"post-bottom": false,
|
"post-bottom": false,
|
||||||
|
@ -43,47 +56,133 @@ const adConfig = Ember.Object.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
const displayCounts = {
|
||||||
@computed("placement")
|
houseAds: 0,
|
||||||
adComponents(placement) {
|
allAds: 0
|
||||||
// Check house ads first
|
};
|
||||||
const houseAds = this.site.get("house_creatives");
|
|
||||||
if (!houseAds || !houseAds.settings) {
|
export default AdComponent.extend({
|
||||||
return [];
|
needsUpdate: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a given ad placement and optionally a post number if in between posts,
|
||||||
|
* list all ad network names that are configured to show there.
|
||||||
|
*/
|
||||||
|
@computed("placement", "postNumber")
|
||||||
|
availableAdTypes(placement, postNumber) {
|
||||||
|
let types = [];
|
||||||
|
const houseAds = this.site.get("house_creatives"),
|
||||||
|
placeUnderscored = placement.replace(/-/g, "_");
|
||||||
|
|
||||||
|
if (houseAds && houseAds.settings) {
|
||||||
|
const adsForSlot = houseAds.settings[placeUnderscored];
|
||||||
|
|
||||||
|
if (
|
||||||
|
Object.keys(houseAds.creatives).length > 0 &&
|
||||||
|
!Ember.isBlank(adsForSlot) &&
|
||||||
|
(!postNumber ||
|
||||||
|
this.isNthPost(parseInt(houseAds.settings.after_nth_post, 10)))
|
||||||
|
) {
|
||||||
|
types.push("house-ad");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const adsForSlot = houseAds.settings[placement.replace(/-/g, "_")];
|
Object.keys(adConfig).forEach(adNetwork => {
|
||||||
|
|
||||||
if (
|
|
||||||
Object.keys(houseAds.creatives).length > 0 &&
|
|
||||||
!Ember.isBlank(adsForSlot)
|
|
||||||
) {
|
|
||||||
return ["house-ad"];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(adConfig).filter(adNetwork => {
|
|
||||||
const config = adConfig[adNetwork];
|
const config = adConfig[adNetwork];
|
||||||
let settingNames = null,
|
let settingNames = null,
|
||||||
name;
|
name;
|
||||||
|
|
||||||
if (this.site.mobileView) {
|
if (
|
||||||
settingNames = config.mobile || config.desktop;
|
config.enabledSetting &&
|
||||||
} else {
|
!Ember.isBlank(this.siteSettings[config.enabledSetting]) &&
|
||||||
settingNames = config.desktop;
|
(!postNumber ||
|
||||||
}
|
!config.nthPost ||
|
||||||
|
this.isNthPost(parseInt(this.siteSettings[config.nthPost], 10)))
|
||||||
|
) {
|
||||||
|
if (this.site.mobileView) {
|
||||||
|
settingNames = config.mobile || config.desktop;
|
||||||
|
} else {
|
||||||
|
settingNames = config.desktop;
|
||||||
|
}
|
||||||
|
|
||||||
if (settingNames) {
|
if (settingNames) {
|
||||||
name = settingNames[placement];
|
name = settingNames[placement];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === undefined) {
|
if (name === undefined) {
|
||||||
// follows naming convention: prefix_(mobile_)_{placement}_code
|
// follows naming convention: prefix_(mobile_)_{placement}_code
|
||||||
name = `${config.settingPrefix}_${
|
name = `${config.settingPrefix}_${
|
||||||
this.site.mobileView ? "mobile_" : ""
|
this.site.mobileView ? "mobile_" : ""
|
||||||
}${placement.replace(/-/g, "_")}_code`;
|
}${placeUnderscored}_code`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return name !== false && !Ember.isBlank(this.siteSettings[name]);
|
if (name !== false && !Ember.isBlank(this.siteSettings[name])) {
|
||||||
|
types.push(adNetwork);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return types;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When house ads are configured to alternate with other ad networks, we
|
||||||
|
* need to trigger an update of which ad component is shown after
|
||||||
|
* navigating between topic lists or topics.
|
||||||
|
*/
|
||||||
|
@observes("refreshOnChange")
|
||||||
|
changed() {
|
||||||
|
if (this.get("listLoading")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// force adComponents to be recomputed
|
||||||
|
this.notifyPropertyChange("needsUpdate");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the names of ad components that should be rendered
|
||||||
|
* in the given ad placement. It handles alternating between house ads
|
||||||
|
* and other ad networks.
|
||||||
|
*/
|
||||||
|
@computed("placement", "availableAdTypes", "needsUpdate")
|
||||||
|
adComponents(placement, availableAdTypes) {
|
||||||
|
if (
|
||||||
|
!availableAdTypes.includes("house-ad") ||
|
||||||
|
availableAdTypes.length === 1
|
||||||
|
) {
|
||||||
|
// Current behaviour is to allow multiple ads from different networks
|
||||||
|
// to show in the same place. We could change this to choose one somehow.
|
||||||
|
return availableAdTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const houseAds = this.site.get("house_creatives");
|
||||||
|
let houseAdsSkipped = false;
|
||||||
|
|
||||||
|
if (houseAds.settings.house_ads_frequency === 100) {
|
||||||
|
// house always wins
|
||||||
|
return ["house-ad"];
|
||||||
|
} else if (houseAds.settings.house_ads_frequency > 0) {
|
||||||
|
// show house ads the given percent of the time
|
||||||
|
if (
|
||||||
|
displayCounts.allAds === 0 ||
|
||||||
|
(100 * displayCounts.houseAds) / displayCounts.allAds <
|
||||||
|
houseAds.settings.house_ads_frequency
|
||||||
|
) {
|
||||||
|
displayCounts.houseAds += 1;
|
||||||
|
displayCounts.allAds += 1;
|
||||||
|
return ["house-ad"];
|
||||||
|
} else {
|
||||||
|
houseAdsSkipped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const networkNames = availableAdTypes.filter(x => x !== "house-ad");
|
||||||
|
|
||||||
|
if (houseAdsSkipped) {
|
||||||
|
displayCounts.allAds += networkNames.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return networkNames;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{{#each adComponents as |adComponent|}}
|
{{#each adComponents as |adComponent|}}
|
||||||
{{component adComponent
|
{{component adComponent
|
||||||
placement=placement
|
placement=placement
|
||||||
refreshOnChange=refreshOnChange
|
refreshOnChange=refreshOnChange
|
||||||
category=category
|
category=category
|
||||||
listLoading=listLoading
|
listLoading=listLoading
|
||||||
postNumber=postNumber}}
|
postNumber=postNumber}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -2,6 +2,7 @@ en:
|
||||||
site_settings:
|
site_settings:
|
||||||
no_ads_for_groups: "Don't show ads to users in these groups."
|
no_ads_for_groups: "Don't show ads to users in these groups."
|
||||||
house_ads_after_nth_post: 'If "Between posts" house ads are defined, show an ad after every N posts, where N is this value.'
|
house_ads_after_nth_post: 'If "Between posts" house ads are defined, show an ad after every N posts, where N is this value.'
|
||||||
|
house_ads_frequency: "If other ad networks are configured to show in an ad slot, how often should house ads be shown, as a percentage."
|
||||||
|
|
||||||
dfp_publisher_id: "Input your Google Ad Manager (formerly called DFP) network code, which is found in your network settings."
|
dfp_publisher_id: "Input your Google Ad Manager (formerly called DFP) network code, which is found in your network settings."
|
||||||
dfp_through_trust_level: "Show your ads to users based on trust levels. Users with trust level higher than this value will not see ads."
|
dfp_through_trust_level: "Show your ads to users based on trust levels. Users with trust level higher than this value will not see ads."
|
||||||
|
|
|
@ -8,6 +8,11 @@ ad_plugin:
|
||||||
default: 20
|
default: 20
|
||||||
min: 1
|
min: 1
|
||||||
max: 10000
|
max: 10000
|
||||||
|
house_ads_frequency:
|
||||||
|
client: true
|
||||||
|
default: 100
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
|
||||||
adsense_plugin:
|
adsense_plugin:
|
||||||
adsense_publisher_code:
|
adsense_publisher_code:
|
||||||
|
|
Loading…
Reference in New Issue