diff --git a/client/app.vue b/client/app.vue index e9a2f33..cdbe80b 100644 --- a/client/app.vue +++ b/client/app.vue @@ -44,6 +44,17 @@ export default { components: {}, setup() { + useOpnSeoMeta({ + title: 'OpnForm', + description: 'Create beautiful forms for free. Unlimited fields, unlimited submissions. It\'s free and it takes less than 1 minute to create your first form.', + ogImage: '/img/social-preview.jpg', + }) + useHead({ + titleTemplate: (titleChunk) => { + return titleChunk ? `${titleChunk} - OpnForm` : 'OpnForm'; + } + }) + const appStore = useAppStore() return { @@ -57,8 +68,6 @@ export default { }, data: () => ({ - metaTitle: 'OpnForm', - metaDescription: 'Create beautiful forms for free. Unlimited fields, unlimited submissions. It\'s free and it takes less than 1 minute to create your first form.', announcement: false, alert: { type: null, diff --git a/client/composables/useOpnSeoMeta.js b/client/composables/useOpnSeoMeta.js new file mode 100644 index 0000000..d07dd52 --- /dev/null +++ b/client/composables/useOpnSeoMeta.js @@ -0,0 +1,16 @@ +export const useOpnSeoMeta = (meta) => { + return useSeoMeta({ + ...meta.title ? { + ogTitle: meta.title, + twitterTitle: meta.title, + } : {}, + ...meta.description ? { + ogDescription: meta.description, + twitterDescription: meta.description, + } : {}, + ...meta.ogImage ? { + twitterImage: meta.ogImage, + } : {}, + ...meta, + }) +} diff --git a/client/mixins/seo-meta.js b/client/mixins/seo-meta.js deleted file mode 100644 index 2d40447..0000000 --- a/client/mixins/seo-meta.js +++ /dev/null @@ -1,23 +0,0 @@ -export default { - metaInfo () { - const title = this.metaTitle ?? 'OpnForm' - const description = this.metaDescription ?? "Create beautiful forms for free. Unlimited fields, unlimited submissions. It's free and it takes less than 1 minute to create your first form." - const image = this.metaImage ?? this.asset('img/social-preview.jpg') - const metaTemplate = this.metaTemplate ?? '%s · OpnForm' - - return { - title: title, - titleTemplate: metaTemplate, - meta: [ - ...(this.metaTags ?? []), - { vmid: 'og:title', property: 'og:title', content: title }, - { vmid: 'twitter:title', property: 'twitter:title', content: title }, - { vmid: 'description', name: 'description', content: description }, - { vmid: 'og:description', property: 'og:description', content: description }, - { vmid: 'twitter:description', property: 'twitter:description', content: description }, - { vmid: 'twitter:image', property: 'twitter:image', content: image }, - { vmid: 'og:image', property: 'og:image', content: image } - ] - } - } -} diff --git a/client/pages/ai-form-builder.vue b/client/pages/ai-form-builder.vue index 94a1646..67de14c 100644 --- a/client/pages/ai-form-builder.vue +++ b/client/pages/ai-form-builder.vue @@ -496,13 +496,16 @@ diff --git a/client/pages/forms/[slug]/show.vue b/client/pages/forms/[slug]/show.vue index 65df2c7..b60ea9d 100644 --- a/client/pages/forms/[slug]/show.vue +++ b/client/pages/forms/[slug]/show.vue @@ -144,6 +144,10 @@ export default { middleware: 'auth', setup () { + useOpnSeoMeta({ + title: 'Home' + }) + const authStore = useAuthStore() const formsStore = useFormsStore() const workingFormStore = useWorkingFormStore() @@ -167,7 +171,6 @@ export default { data () { return { - metaTitle: 'Home', tabsList: [ { name: 'Submissions', diff --git a/client/pages/forms/[slug]/show/share.vue b/client/pages/forms/[slug]/show/share.vue index fd663fc..f768a0b 100644 --- a/client/pages/forms/[slug]/show/share.vue +++ b/client/pages/forms/[slug]/show/share.vue @@ -26,7 +26,6 @@ import EmbedCode from '../../../../components/pages/forms/show/EmbedCode.vue' import FormQrCode from '../../../../components/pages/forms/show/FormQrCode.vue' import UrlFormPrefill from '../../../../components/pages/forms/show/UrlFormPrefill.vue' import RegenerateFormLink from '../../../../components/pages/forms/show/RegenerateFormLink.vue' -import SeoMeta from '../../../../mixins/seo-meta.js' import AdvancedFormUrlSettings from '../../../../components/open/forms/components/AdvancedFormUrlSettings.vue' import EmbedFormAsPopupModal from '../../../../components/pages/forms/show/EmbedFormAsPopupModal.vue' @@ -45,6 +44,12 @@ export default { form: {type: Object, required: true}, }, + setup (props) { + useOpnSeoMeta({ + title: (props.form) ? 'Share Form - '+props.form.title : 'Share Form' + }) + }, + data: () => ({ shareFormConfig: { hide_title: false, @@ -53,9 +58,6 @@ export default { }), computed: { - metaTitle() { - return (this.form) ? 'Form Share - '+this.form.title : 'Form Share' - }, shareUrlForQueryParams () { let queryStr = '' for (const [key, value] of Object.entries(this.shareFormConfig)) { diff --git a/client/pages/forms/[slug]/show/stats.vue b/client/pages/forms/[slug]/show/stats.vue index 414641b..c8ab487 100644 --- a/client/pages/forms/[slug]/show/stats.vue +++ b/client/pages/forms/[slug]/show/stats.vue @@ -9,7 +9,6 @@ diff --git a/client/pages/forms/[slug]/show/submissions.vue b/client/pages/forms/[slug]/show/submissions.vue index ea141e8..6ac31a1 100644 --- a/client/pages/forms/[slug]/show/submissions.vue +++ b/client/pages/forms/[slug]/show/submissions.vue @@ -6,14 +6,18 @@ diff --git a/client/pages/pricing.vue b/client/pages/pricing.vue index d5e9a9b..a0a7f4b 100644 --- a/client/pages/pricing.vue +++ b/client/pages/pricing.vue @@ -245,6 +245,11 @@ export default { layout: 'default', setup () { + useOpnSeoMeta({ + title: 'Pricing', + description: 'All of our core features are free, and there is no quantity limit. You can also created more advanced and customized forms with OpnForms Pro.' + }) + definePageMeta({ middleware: [ function (to, from) { @@ -264,15 +269,6 @@ export default { } }, - data: () => ({ - metaTitle: 'Pricing', - metaDescription: 'All of our core features are free, and there is no quantity limit. You can also created more advanced and customized forms with OpnForms Pro.', - }), - - mounted() {}, - - computed: {}, - methods: { contactUs() { window.$crisp.push(['do', 'chat:show']) diff --git a/client/pages/privacy-policy.vue b/client/pages/privacy-policy.vue index 898b56e..d74a93a 100644 --- a/client/pages/privacy-policy.vue +++ b/client/pages/privacy-policy.vue @@ -13,12 +13,13 @@ - \ No newline at end of file diff --git a/client/pages/settings/account.vue b/client/pages/settings/account.vue index b08f159..32b64f9 100644 --- a/client/pages/settings/account.vue +++ b/client/pages/settings/account.vue @@ -20,15 +20,18 @@ import { useRouter } from 'vue-router'; const router = useRouter() const authStore = useAuthStore() -const metaTitle = 'Account' let loading = false +useOpnSeoMeta({ + title: 'Account' +}) + const deleteAccount = () => { loading = true opnFetch('/user', {method:'DELETE'}).then(async (data) => { loading = false useAlert().success(data.message) - + // Log out the user. await authStore.logout() diff --git a/client/pages/settings/admin.vue b/client/pages/settings/admin.vue index e9d80bf..b168fb3 100644 --- a/client/pages/settings/admin.vue +++ b/client/pages/settings/admin.vue @@ -41,7 +41,10 @@ definePageMeta({ middleware: "admin" }) -const metaTitle = 'Admin' +useOpnSeoMeta({ + title: 'Admin' +}) + const authStore = useAuthStore() const workspacesStore = useWorkspacesStore() const router = useRouter() diff --git a/client/pages/settings/billing.vue b/client/pages/settings/billing.vue index 4eabbb4..0ad4afc 100644 --- a/client/pages/settings/billing.vue +++ b/client/pages/settings/billing.vue @@ -24,7 +24,10 @@ import { computed } from 'vue' import { useAuthStore } from '../../stores/auth' import AppSumoBilling from '../../components/vendor/appsumo/AppSumoBilling.vue' -const metaTitle = 'Billing' +useOpnSeoMeta({ + title: 'Billing' +}) + const authStore = useAuthStore() let user = computed(() => authStore.user) let billingLoading = false diff --git a/client/pages/settings/password.vue b/client/pages/settings/password.vue index 5db6033..bf0bd47 100644 --- a/client/pages/settings/password.vue +++ b/client/pages/settings/password.vue @@ -25,7 +25,10 @@